From 354bb40e75d94466e91fe6960523612c9d17ccfb Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 2 Nov 2017 23:11:29 +0300 Subject: Add implementation --- mysql/extra/yassl/COPYING | 340 ++ mysql/extra/yassl/FLOSS-EXCEPTIONS | 121 + mysql/extra/yassl/README | 786 ++++ mysql/extra/yassl/include/buffer.hpp | 211 ++ mysql/extra/yassl/include/cert_wrapper.hpp | 137 + mysql/extra/yassl/include/crypto_wrapper.hpp | 428 +++ mysql/extra/yassl/include/factory.hpp | 101 + mysql/extra/yassl/include/handshake.hpp | 69 + mysql/extra/yassl/include/lock.hpp | 96 + mysql/extra/yassl/include/log.hpp | 55 + mysql/extra/yassl/include/openssl/crypto.h | 33 + mysql/extra/yassl/include/openssl/des.h | 20 + mysql/extra/yassl/include/openssl/des_old.h | 20 + mysql/extra/yassl/include/openssl/engine.h | 24 + mysql/extra/yassl/include/openssl/err.h | 27 + mysql/extra/yassl/include/openssl/evp.h | 29 + mysql/extra/yassl/include/openssl/hmac.h | 20 + mysql/extra/yassl/include/openssl/lhash.h | 21 + mysql/extra/yassl/include/openssl/md4.h | 20 + mysql/extra/yassl/include/openssl/md5.h | 23 + mysql/extra/yassl/include/openssl/objects.h | 20 + mysql/extra/yassl/include/openssl/opensslv.h | 31 + mysql/extra/yassl/include/openssl/pem.h | 20 + mysql/extra/yassl/include/openssl/pkcs12.h | 24 + mysql/extra/yassl/include/openssl/prefix_crypto.h | 20 + mysql/extra/yassl/include/openssl/prefix_ssl.h | 189 + mysql/extra/yassl/include/openssl/rand.h | 21 + mysql/extra/yassl/include/openssl/rsa.h | 29 + mysql/extra/yassl/include/openssl/sha.h | 20 + mysql/extra/yassl/include/openssl/ssl.h | 568 +++ .../extra/yassl/include/openssl/transport_types.h | 26 + mysql/extra/yassl/include/openssl/x509.h | 20 + mysql/extra/yassl/include/openssl/x509v3.h | 20 + mysql/extra/yassl/include/socket_wrapper.hpp | 104 + mysql/extra/yassl/include/timer.hpp | 40 + mysql/extra/yassl/include/yassl.hpp | 85 + mysql/extra/yassl/include/yassl_error.hpp | 88 + mysql/extra/yassl/include/yassl_imp.hpp | 748 ++++ mysql/extra/yassl/include/yassl_int.hpp | 725 ++++ mysql/extra/yassl/include/yassl_types.hpp | 540 +++ mysql/extra/yassl/src/buffer.cpp | 330 ++ mysql/extra/yassl/src/cert_wrapper.cpp | 408 ++ mysql/extra/yassl/src/crypto_wrapper.cpp | 1016 +++++ mysql/extra/yassl/src/get_password.c | 218 ++ mysql/extra/yassl/src/handshake.cpp | 1190 ++++++ mysql/extra/yassl/src/lock.cpp | 87 + mysql/extra/yassl/src/log.cpp | 147 + mysql/extra/yassl/src/socket_wrapper.cpp | 238 ++ mysql/extra/yassl/src/ssl.cpp | 1883 ++++++++++ mysql/extra/yassl/src/timer.cpp | 80 + mysql/extra/yassl/src/yassl_error.cpp | 288 ++ mysql/extra/yassl/src/yassl_imp.cpp | 2642 +++++++++++++ mysql/extra/yassl/src/yassl_int.cpp | 2826 ++++++++++++++ mysql/extra/yassl/taocrypt/COPYING | 340 ++ mysql/extra/yassl/taocrypt/README | 48 + mysql/extra/yassl/taocrypt/include/aes.hpp | 155 + mysql/extra/yassl/taocrypt/include/algebra.hpp | 226 ++ mysql/extra/yassl/taocrypt/include/arc4.hpp | 58 + mysql/extra/yassl/taocrypt/include/asn.hpp | 392 ++ mysql/extra/yassl/taocrypt/include/block.hpp | 202 + mysql/extra/yassl/taocrypt/include/blowfish.hpp | 88 + mysql/extra/yassl/taocrypt/include/coding.hpp | 91 + mysql/extra/yassl/taocrypt/include/des.hpp | 130 + mysql/extra/yassl/taocrypt/include/dh.hpp | 86 + mysql/extra/yassl/taocrypt/include/dsa.hpp | 126 + mysql/extra/yassl/taocrypt/include/error.hpp | 88 + mysql/extra/yassl/taocrypt/include/file.hpp | 130 + mysql/extra/yassl/taocrypt/include/hash.hpp | 110 + mysql/extra/yassl/taocrypt/include/hc128.hpp | 63 + mysql/extra/yassl/taocrypt/include/hmac.hpp | 138 + mysql/extra/yassl/taocrypt/include/integer.hpp | 332 ++ mysql/extra/yassl/taocrypt/include/kernelc.hpp | 34 + mysql/extra/yassl/taocrypt/include/md2.hpp | 64 + mysql/extra/yassl/taocrypt/include/md4.hpp | 62 + mysql/extra/yassl/taocrypt/include/md5.hpp | 70 + mysql/extra/yassl/taocrypt/include/misc.hpp | 888 +++++ mysql/extra/yassl/taocrypt/include/modarith.hpp | 165 + mysql/extra/yassl/taocrypt/include/modes.hpp | 154 + mysql/extra/yassl/taocrypt/include/pwdbased.hpp | 91 + mysql/extra/yassl/taocrypt/include/rabbit.hpp | 65 + mysql/extra/yassl/taocrypt/include/random.hpp | 84 + mysql/extra/yassl/taocrypt/include/ripemd.hpp | 69 + mysql/extra/yassl/taocrypt/include/rsa.hpp | 250 ++ mysql/extra/yassl/taocrypt/include/runtime.hpp | 60 + mysql/extra/yassl/taocrypt/include/sha.hpp | 174 + mysql/extra/yassl/taocrypt/include/twofish.hpp | 94 + mysql/extra/yassl/taocrypt/include/type_traits.hpp | 77 + mysql/extra/yassl/taocrypt/include/types.hpp | 99 + mysql/extra/yassl/taocrypt/mySTL/algorithm.hpp | 108 + mysql/extra/yassl/taocrypt/mySTL/helpers.hpp | 153 + mysql/extra/yassl/taocrypt/mySTL/list.hpp | 367 ++ mysql/extra/yassl/taocrypt/mySTL/memory.hpp | 136 + mysql/extra/yassl/taocrypt/mySTL/memory_array.hpp | 135 + mysql/extra/yassl/taocrypt/mySTL/pair.hpp | 58 + mysql/extra/yassl/taocrypt/mySTL/stdexcept.hpp | 76 + mysql/extra/yassl/taocrypt/mySTL/vector.hpp | 153 + mysql/extra/yassl/taocrypt/src/aes.cpp | 1885 ++++++++++ mysql/extra/yassl/taocrypt/src/aestables.cpp | 36 + mysql/extra/yassl/taocrypt/src/algebra.cpp | 336 ++ mysql/extra/yassl/taocrypt/src/arc4.cpp | 243 ++ mysql/extra/yassl/taocrypt/src/asn.cpp | 1348 +++++++ mysql/extra/yassl/taocrypt/src/coding.cpp | 266 ++ mysql/extra/yassl/taocrypt/src/des.cpp | 778 ++++ mysql/extra/yassl/taocrypt/src/dh.cpp | 103 + mysql/extra/yassl/taocrypt/src/dsa.cpp | 274 ++ mysql/extra/yassl/taocrypt/src/file.cpp | 115 + mysql/extra/yassl/taocrypt/src/hash.cpp | 191 + mysql/extra/yassl/taocrypt/src/hc128.cpp | 317 ++ mysql/extra/yassl/taocrypt/src/integer.cpp | 3894 ++++++++++++++++++++ mysql/extra/yassl/taocrypt/src/md2.cpp | 125 + mysql/extra/yassl/taocrypt/src/md4.cpp | 157 + mysql/extra/yassl/taocrypt/src/md5.cpp | 506 +++ mysql/extra/yassl/taocrypt/src/misc.cpp | 297 ++ mysql/extra/yassl/taocrypt/src/rabbit.cpp | 255 ++ mysql/extra/yassl/taocrypt/src/random.cpp | 138 + mysql/extra/yassl/taocrypt/src/ripemd.cpp | 844 +++++ mysql/extra/yassl/taocrypt/src/rsa.cpp | 215 ++ mysql/extra/yassl/taocrypt/src/sha.cpp | 1033 ++++++ 118 files changed, 37117 insertions(+) create mode 100644 mysql/extra/yassl/COPYING create mode 100644 mysql/extra/yassl/FLOSS-EXCEPTIONS create mode 100644 mysql/extra/yassl/README create mode 100644 mysql/extra/yassl/include/buffer.hpp create mode 100644 mysql/extra/yassl/include/cert_wrapper.hpp create mode 100644 mysql/extra/yassl/include/crypto_wrapper.hpp create mode 100644 mysql/extra/yassl/include/factory.hpp create mode 100644 mysql/extra/yassl/include/handshake.hpp create mode 100644 mysql/extra/yassl/include/lock.hpp create mode 100644 mysql/extra/yassl/include/log.hpp create mode 100644 mysql/extra/yassl/include/openssl/crypto.h create mode 100644 mysql/extra/yassl/include/openssl/des.h create mode 100644 mysql/extra/yassl/include/openssl/des_old.h create mode 100644 mysql/extra/yassl/include/openssl/engine.h create mode 100644 mysql/extra/yassl/include/openssl/err.h create mode 100644 mysql/extra/yassl/include/openssl/evp.h create mode 100644 mysql/extra/yassl/include/openssl/hmac.h create mode 100644 mysql/extra/yassl/include/openssl/lhash.h create mode 100644 mysql/extra/yassl/include/openssl/md4.h create mode 100644 mysql/extra/yassl/include/openssl/md5.h create mode 100644 mysql/extra/yassl/include/openssl/objects.h create mode 100644 mysql/extra/yassl/include/openssl/opensslv.h create mode 100644 mysql/extra/yassl/include/openssl/pem.h create mode 100644 mysql/extra/yassl/include/openssl/pkcs12.h create mode 100644 mysql/extra/yassl/include/openssl/prefix_crypto.h create mode 100644 mysql/extra/yassl/include/openssl/prefix_ssl.h create mode 100644 mysql/extra/yassl/include/openssl/rand.h create mode 100644 mysql/extra/yassl/include/openssl/rsa.h create mode 100644 mysql/extra/yassl/include/openssl/sha.h create mode 100644 mysql/extra/yassl/include/openssl/ssl.h create mode 100644 mysql/extra/yassl/include/openssl/transport_types.h create mode 100644 mysql/extra/yassl/include/openssl/x509.h create mode 100644 mysql/extra/yassl/include/openssl/x509v3.h create mode 100644 mysql/extra/yassl/include/socket_wrapper.hpp create mode 100644 mysql/extra/yassl/include/timer.hpp create mode 100644 mysql/extra/yassl/include/yassl.hpp create mode 100644 mysql/extra/yassl/include/yassl_error.hpp create mode 100644 mysql/extra/yassl/include/yassl_imp.hpp create mode 100644 mysql/extra/yassl/include/yassl_int.hpp create mode 100644 mysql/extra/yassl/include/yassl_types.hpp create mode 100644 mysql/extra/yassl/src/buffer.cpp create mode 100644 mysql/extra/yassl/src/cert_wrapper.cpp create mode 100644 mysql/extra/yassl/src/crypto_wrapper.cpp create mode 100644 mysql/extra/yassl/src/get_password.c create mode 100644 mysql/extra/yassl/src/handshake.cpp create mode 100644 mysql/extra/yassl/src/lock.cpp create mode 100644 mysql/extra/yassl/src/log.cpp create mode 100644 mysql/extra/yassl/src/socket_wrapper.cpp create mode 100644 mysql/extra/yassl/src/ssl.cpp create mode 100644 mysql/extra/yassl/src/timer.cpp create mode 100644 mysql/extra/yassl/src/yassl_error.cpp create mode 100644 mysql/extra/yassl/src/yassl_imp.cpp create mode 100644 mysql/extra/yassl/src/yassl_int.cpp create mode 100644 mysql/extra/yassl/taocrypt/COPYING create mode 100644 mysql/extra/yassl/taocrypt/README create mode 100644 mysql/extra/yassl/taocrypt/include/aes.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/algebra.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/arc4.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/asn.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/block.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/blowfish.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/coding.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/des.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/dh.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/dsa.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/error.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/file.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/hash.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/hc128.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/hmac.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/integer.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/kernelc.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/md2.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/md4.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/md5.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/misc.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/modarith.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/modes.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/pwdbased.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/rabbit.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/random.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/ripemd.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/rsa.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/runtime.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/sha.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/twofish.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/type_traits.hpp create mode 100644 mysql/extra/yassl/taocrypt/include/types.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/algorithm.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/helpers.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/list.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/memory.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/memory_array.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/pair.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/stdexcept.hpp create mode 100644 mysql/extra/yassl/taocrypt/mySTL/vector.hpp create mode 100644 mysql/extra/yassl/taocrypt/src/aes.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/aestables.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/algebra.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/arc4.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/asn.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/coding.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/des.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/dh.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/dsa.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/file.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/hash.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/hc128.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/integer.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/md2.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/md4.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/md5.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/misc.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/rabbit.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/random.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/ripemd.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/rsa.cpp create mode 100644 mysql/extra/yassl/taocrypt/src/sha.cpp (limited to 'mysql/extra') diff --git a/mysql/extra/yassl/COPYING b/mysql/extra/yassl/COPYING new file mode 100644 index 0000000..845980a --- /dev/null +++ b/mysql/extra/yassl/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/mysql/extra/yassl/FLOSS-EXCEPTIONS b/mysql/extra/yassl/FLOSS-EXCEPTIONS new file mode 100644 index 0000000..47f86ff --- /dev/null +++ b/mysql/extra/yassl/FLOSS-EXCEPTIONS @@ -0,0 +1,121 @@ +yaSSL FLOSS License Exception +**************************************** + +Version 0.2, 31 August 2006 + +The Sawtooth Consulting Ltd. Exception for Free/Libre and Open Source +Software-only Applications Using yaSSL Libraries (the "FLOSS Exception"). + +*Exception Intent* + +We want specified Free/Libre and Open Source Software ("FLOSS") +applications to be able to use specified GPL-licensed yaSSL +libraries (the "Program") despite the fact that not all FLOSS +licenses are compatible with version 2 of the GNU General Public +License (the "GPL"). + +*Legal Terms and Conditions* + +As a special exception to the terms and conditions of version 2.0 of +the GPL: + + 1. You are free to distribute a Derivative Work that is formed + entirely from the Program and one or more works (each, a "FLOSS + Work") licensed under one or more of the licenses listed below + in section 1, as long as: + + 1. You obey the GPL in all respects for the Program and the + Derivative Work, except for identifiable sections of the + Derivative Work which are not derived from the Program, + and which can reasonably be considered independent and + separate works in themselves, + + 2. all identifiable sections of the Derivative Work which + are not derived from the Program, and which can reasonably be + considered independent and separate works in themselves, + + * i + + are distributed subject to one of the FLOSS licenses + listed below, and + + * ii + + the object code or executable form of those sections are + accompanied by the complete corresponding machine-readable + source code for those sections on the same medium and under + the same FLOSS license as the corresponding object code or + executable forms of those sections, and + + + 3. any works which are aggregated with the Program or with + a Derivative Work on a volume of a storage or distribution + medium in accordance with the GPL, can reasonably be considered + independent and separate works in themselves which are not + derivatives of either the Program, a Derivative Work or a FLOSS + Work. + + + If the above conditions are not met, then the Program may only be + copied, modified, distributed or used under the terms and + conditions of the GPL or another valid licensing option from + Sawtooth Consulting Ltd. + + 2. FLOSS License List + + *License name* *Version(s)/Copyright Date* + Academic Free License 2.0 + Apache Software License 1.0/1.1/2.0 + Apple Public Source License 2.0 + Artistic license From Perl 5.8.0 + BSD license "July 22 1999" + Common Development and Distribution License (CDDL) 1.0 + Common Public License 1.0 + GNU Library or "Lesser" General Public 2.0/2.1 + License (LGPL) + Jabber Open Source License 1.0 + MIT license - + Mozilla Public License (MPL) 1.0/1.1 + Open Software License 2.0 + PHP License 3.0 + Python license (CNRI Python License) - + Python Software Foundation License 2.1.1 + Sleepycat License "1999" + University of Illinois/NCSA Open Source License - + W3C License "2001" + X11 License "2001" + Zlib/libpng License - + Zope Public License 2.0 + + Due to the many variants of some of the above licenses, we require + that any version follow the 2003 version of the Free Software + Foundation's Free Software Definition + (http://www.gnu.org/philosophy/free-sw.html + (http://www.gnu.org/philosophy/free-sw.html)) or version 1.9 of + the Open Source Definition by the Open Source Initiative + (http://www.opensource.org/docs/definition.php + (http://www.opensource.org/docs/definition.php)). + + 3. Definitions + + 1. Terms used, but not defined, herein shall have the + meaning provided in the GPL. + + 2. Derivative Work means a derivative work under copyright + law. + + + 4. Applicability This FLOSS Exception applies to all Programs that + contain a notice placed by Sawtooth Consulting Ltd. saying that the + Program may be distributed under the terms of this FLOSS Exception. + If you create or distribute a work which is a Derivative Work of + both the Program and any other work licensed under the GPL, then + this FLOSS Exception is not available for that work; thus, you + must remove the FLOSS Exception notice from that work and + comply with the GPL in all respects, including by retaining all + GPL notices. You may choose to redistribute a copy of the + Program exclusively under the terms of the GPL by removing the + FLOSS Exception notice from that copy of the Program, provided + that the copy has never been modified by you or any third party. + + diff --git a/mysql/extra/yassl/README b/mysql/extra/yassl/README new file mode 100644 index 0000000..de1bf51 --- /dev/null +++ b/mysql/extra/yassl/README @@ -0,0 +1,786 @@ +*** Note, Please read *** + +yaSSL takes a different approach to certificate verification than OpenSSL does. +The default policy for the client is to verify the server, this means that if +you don't load CAs to verify the server you'll get a connect error, unable to +verify. It you want to mimic OpenSSL behavior of not verifying the server and +reducing security you can do this by calling: + +SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + +before calling SSL_new(); + +*** end Note *** + +yaSSL Release notes, version 2.4.4 (8/8/2017) + This release of yaSSL fixes an interop issue. A fix for detecting cipher + suites with non leading zeros is included as yaSSL only supports cipher + suites with leading zeros. Thanks for the report from Security Innovation + and Oracle. + + Users interoping with other SSL stacks should update. + +yaSSL Release notes, version 2.4.2 (9/22/2016) + This release of yaSSL fixes a medium security vulnerability. A fix for + potential AES side channel leaks is included that a local user monitoring + the same CPU core cache could exploit. VM users, hyper-threading users, + and users where potential attackers have access to the CPU cache will need + to update if they utilize AES. + + DSA padding fixes for unusual sizes is included as well. Users with DSA + certficiates should update. + +yaSSL Release notes, version 2.4.0 (5/20/2016) + This release of yaSSL fixes the OpenSSL compatibility function + SSL_CTX_load_verify_locations() when using the path directory to allow + unlimited path sizes. Minor Windows build fixes are included. + No high level security fixes in this version but we always recommend + updating. + + +yaSSL Release notes, version 2.3.9b (2/03/2016) + This release of yaSSL fixes the OpenSSL compatibility function + X509_NAME_get_index_by_NID() to use the actual index of the common name + instead of searching on the format prefix. Thanks for the report from + yashwant.sahu@oracle.com . Anyone using this function should update. + +yaSSL Release notes, version 2.3.9 (12/01/2015) + This release of yaSSL fixes two client side Diffie-Hellman problems. + yaSSL was only handling the cases of zero or one leading zeros for the key + agreement instead of potentially any number. This caused about 1 in 50,000 + connections to fail when using DHE cipher suites. The second problem was + the case where a server would send a public value shorter than the prime + value, causing about 1 in 128 client connections to fail, and also + caused the yaSSL client to read off the end of memory. All client side + DHE cipher suite users should update. + Thanks to Adam Langely (agl@imperialviolet.org) for the detailed report! + +yaSSL Release notes, version 2.3.8 (9/17/2015) + This release of yaSSL fixes a high security vulnerability. All users + SHOULD update. If using yaSSL for TLS on the server side with private + RSA keys allowing ephemeral key exchange you MUST update and regenerate + the RSA private keys. This report is detailed in: + https://people.redhat.com/~fweimer/rsa-crt-leaks.pdf + yaSSL now detects RSA signature faults and returns an error. + +yaSSL Patch notes, version 2.3.7e (6/26/2015) + This release of yaSSL includes a fix for Date less than comparison. + Previously yaSSL would return true on less than comparisons if the Dates + were equal. Reported by Oracle. No security problem, but if a cert was + generated right now, a server started using it in the same second, and a + client tried to verify it in the same second it would report not yet valid. + +yaSSL Patch notes, version 2.3.7d (6/22/2015) + This release of yaSSL includes a fix for input_buffer set_current with + index 0. SSL_peek() at front of waiting data could trigger. Robert + Golebiowski of Oracle identified and suggested a fix, thanks! + +yaSSL Patch notes, version 2.3.7c (6/12/2015) + This release of yaSSL does certificate DATE comparisons to the second + instead of to the minute, helpful when using freshly generated certs. + Though keep in mind that time sync differences could still show up. + +yaSSL Patch notes, version 2.3.7b (3/18/2015) + This release of yaSSL fixes a potential crash with corrupted private keys. + Also detects bad keys earlier for user. + +yaSSL Release notes, version 2.3.7 (12/10/2014) + This release of yaSSL fixes the potential to process duplicate handshake + messages by explicitly marking/checking received handshake messages. + +yaSSL Release notes, version 2.3.6 (11/25/2014) + + This release of yaSSL fixes some valgrind warnings/errors including + uninitialized reads and off by one index errors induced from fuzzing + the handshake. These were reported by Oracle. + +yaSSL Release notes, version 2.3.5 (9/29/2014) + + This release of yaSSL fixes an RSA Padding check vulnerability reported by + Intel Security Advanced Threat Research team + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +yaSSL Release notes, version 2.3.4 (8/15/2014) + + This release of yaSSL adds checking to the input_buffer class itself. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +yaSSL Release notes, version 2.3.2 (7/25/2014) + + This release of yaSSL updates test certs. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.3.0 (12/5/2013) + + This release of yaSSL updates asm for newer GCC versions. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.2.3 (4/23/2013) + + This release of yaSSL updates the test certificates as they were expired + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.2.2d (2/5/2013) + + This release of yaSSL contains countermeasuers for the Lucky 13 TLS 1.1 + CBC timing padding attack identified by Nadhem AlFardan and Kenneth Paterson + see: http://www.isg.rhul.ac.uk/tls/ + + It also adds SHA2 certificate verification and better checks for malicious + input. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.2.2 (7/5/2012) + + This release of yaSSL contains bug fixes and more security checks around + malicious certificates. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.1.2 (9/2/2011) + + This release of yaSSL contains bug fixes, better non-blocking support with + SSL_write, and OpenSSL RSA public key format support. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.0.0 (7/6/2010) + + This release of yaSSL contains bug fixes, new testing certs, + and a security patch for a potential heap overflow on forged application + data processing. Vulnerability discovered by Matthieu Bonetti from VUPEN + Security http://www.vupen.com. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.9 (1/26/2010) + + This release of yaSSL contains bug fixes, the removal of assert() s and + a security patch for a buffer overflow possibility in certificate name + processing. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.8 (10/14/09) + + This release of yaSSL contains bug fixes and adds new stream ciphers + Rabbit and HC-128 + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.6 (11/13/08) + + This release of yaSSL contains bug fixes, adds autconf shared library + support and has better server suite detection based on certficate and + private key. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.2 (9/24/08) + + This release of yaSSL contains bug fixes and improved certificate verify + callback support. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.8.8 (5/7/08) + + This release of yaSSL contains bug fixes, and better socket handling. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.8.6 (1/31/08) + + This release of yaSSL contains bug fixes, and fixes security problems + associated with using SSL 2.0 client hellos and improper input handling. + Please upgrade to this version if you are using a previous one. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.7.5 (10/15/07) + + This release of yaSSL contains bug fixes, adds MSVC 2005 project support, + GCC 4.2 support, IPV6 support and test, and new test certificates. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.7.2 (8/20/07) + + This release of yaSSL contains bug fixes and adds initial OpenVPN support. + Just configure at this point and beginning of build. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.6.8 (4/16/07) + + This release of yaSSL contains bug fixes and adds SHA-256, SHA-512, SHA-224, + and SHA-384. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.6.0 (2/22/07) + + This release of yaSSL contains bug fixes, portability enhancements, and + better X509 support. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + +*****************yaSSL Release notes, version 1.5.8 (1/10/07) + + This release of yaSSL contains bug fixes, portability enhancements, and + support for GCC 4.1.1 and vs2005 sp1. + + + + Since yaSSL now supports zlib, as does libcurl, the libcurl build test can + fail if yaSSL is built with zlib support since the zlib library isn't + passed. You can do two things to fix this: + + 1) build yaSSL w/o zlib --without-zlib + 2) or add flags to curl configure LDFLAGS="-lm -lz" + + + +*****************yaSSL Release notes, version 1.5.0 (11/09/06) + + This release of yaSSL contains bug fixes, portability enhancements, + and full TLS 1.1 support. Use the functions: + + SSL_METHOD *TLSv1_1_server_method(void); + SSL_METHOD *TLSv1_1_client_method(void); + + or the SSLv23 versions (even though yaSSL doesn't support SSL 2.0 the v23 + means to pick the highest of SSL 3.0, TLS 1.0, or TLS 1.1). + + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + + +****************yaSSL Release notes, version 1.4.5 (10/15/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + zlib compression support, removal of assembly instructions at runtime if + not supported, and initial TLS 1.1 support. + + + Compression Notes: yaSSL uses zlib for compression and the compression + should only be used if yaSSL is at both ends because the implementation + details aren't yet standard. If you'd like to turn compression on use + the SSL_set_compression() function on the client before calling + SSL_connect(). If both the client and server were built with zlib support + then the connection will use compression. If the client isn't built with + support then SSL_set_compression() will return an error (-1). + + To build yaSSL with zlib support on Unix simply have zlib support on your + system and configure will find it if it's in the standard locations. If + it's somewhere else use the option ./configure --with-zlib=DIR. If you'd + like to disable compression support in yaSSL use ./configure --without-zlib. + + To build yaSSL with zlib support on Windows: + + 1) download zlib from http://www.zlib.net/ + 2) follow the instructions in zlib from projects/visualc6/README.txt + for how to add the zlib project into the yaSSL workspace noting that + you'll need to add configuration support for "Win32 Debug" and + "Win32 Release" in note 3 under "To use:". + 3) define HAVE_LIBZ when building yaSSL + + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.4.0 (08/13/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + nonblocking connect and accept, better OpenSSL error mapping, and + certificate caching for session resumption. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.3.7 (06/26/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + and libcurl 7.15.4 support (any newer versions may not build). + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.3.5 (06/01/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + better libcurl support, and improved non-blocking I/O. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.3.0 (04/26/06) + + + This release of yaSSL contains minor bug fixes, portability enhancements, + and libcurl support. + +See normal build instructions below under 1.0.6. + + +--To build for libcurl on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + To build for libcurl the library needs to be built without C++ globals since + the linker will be called in a C context, also libcurl configure will expect + OpenSSL library names so some symbolic links are created. + + ./configure --enable-pure-c + make + make openssl-links + + (then go to your libcurl home and tell libcurl about yaSSL build dir) + ./configure --with-ssl=/yaSSL-BuildDir LDFLAGS=-lm + make + + +--To build for libcurl on Win32: + + Simply add the yaSSL project as a dependency to libcurl, add + yaSSL-Home\include and yaSSL-Home\include\openssl to the include list, and + define USE_SSLEAY and USE_OPENSSL + + please email todd@yassl.com if you have any questions. + + +*******************yaSSL Release notes, version 1.2.2 (03/27/06) + + + This release of yaSSL contains minor bug fixes and portability enhancements. + +See build instructions below under 1.0.6: + + + +*******************yaSSL Release notes, version 1.2.0 + + + This release of yaSSL contains minor bug fixes, portability enhancements, + Diffie-Hellman compatibility fixes for other servers and client, + optimization improvements, and x86 ASM changes. + +See build instructions below under 1.0.6: + + + +*****************yaSSL Release notes, version 1.1.5 + + This release of yaSSL contains minor bug fixes, portability enhancements, + and user requested changes including the ability to add all certificates in + a directory, more robust socket handling, no new overloading unless + requested, and an SSL_VERIFY_NONE option. + + +See build instructions below under 1.0.6: + + + +******************yaSSL Release notes, version 1.0.6 + +This release of yaSSL contains minor bug fixes, portability enhancements, +x86 assembly for ARC4, SHA, MD5, and RIPEMD, --enable-ia32-asm configure +option, and a security patch for certificate chain processing. + +--To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + ./configure + make + + run testsuite from yaSSL-Home/testsuite to test the build + +to make a release build: + + ./configure --disable-debug + make + + run testsuite from yaSSL-Home/testsuite to test the build + + +--To build on Win32 + +Choose (Re)Build All from the project workspace + +run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build + + + +***************** yaSSL Release notes, version 1.0.5 + +This release of yaSSL contains minor bug fixes, portability enhancements, +x86 assembly for AES, 3DES, BLOWFISH, and TWOFISH, --without-debug configure +option, and --enable-kernel-mode configure option for using TaoCrypt with +kernel modules. + +--To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + ./configure + make + + run testsuite from yaSSL-Home/testsuite to test the build + +to make a release build: + + ./configure --without-debug + make + + run testsuite from yaSSL-Home/testsuite to test the build + + +--To build on Win32 + +Choose (Re)Build All from the project workspace + +run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build + + +******************yaSSL Release notes, version 1.0.1 + +This release of yaSSL contains minor bug fixes, portability enhancements, +GCC 3.4.4 support, MSVC 2003 support, and more documentation. + +Please see build instructions in the release notes for 0.9.6 below. + + +******************yaSSL Release notes, version 1.0 + +This release of yaSSL contains minor bug fixes, portability enhancements, +GCC 4.0 support, testsuite, improvements, and API additions. + +Please see build instructions in the release notes for 0.9.6 below. + + +******************yaSSL Release notes, version 0.9.9 + +This release of yaSSL contains minor bug fixes, portability enchancements, +MSVC 7 support, memory improvements, and API additions. + +Please see build instructions in the release notes for 0.9.6 below. + + +******************yaSSL Release notes, version 0.9.8 + +This release of yaSSL contains minor bug fixes and portability enchancements. + +Please see build instructions in the release notes for 0.9.6 below. + + +******************yaSSL Release notes, version 0.9.6 + +This release of yaSSL contains minor bug fixes, removal of STL support, and +removal of exceptions and rtti so that the library can be linked without the +std c++ library. + +--To build on Linux, Solaris, FreeBSD, Mac OS X, or Cygwin + +./configure +make + +run testsuite from yaSSL-Home/testsuite to test the build + + +--To build on Win32 + +Choose (Re)Build All from the project workspace + +run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build + + + +******************yaSSL Release notes, version 0.9.2 + +This release of yaSSL contains minor bug fixes, expanded certificate +verification and chaining, and improved documentation. + +Please see build instructions in release notes 0.3.0. + + + +******************yaSSL Release notes, version 0.9.0 + +This release of yaSSL contains minor bug fixes, client verification handling, +hex and base64 encoing/decoding, and an improved test suite. + +Please see build instructions in release notes 0.3.0. + + +******************yaSSL Release notes, version 0.8.0 + +This release of yaSSL contains minor bug fixes, and initial porting effort to +64bit, BigEndian, and more UNIX systems. + +Please see build instructions in release notes 0.3.0. + + +******************yaSSL Release notes, version 0.6.0 + +This release of yaSSL contains minor bug fixes, source cleanup, and binary beta +(1) of the yaSSL libraries. + +Please see build instructions in release notes 0.3.0. + + + +******************yaSSL Release notes, version 0.5.0 + +This release of yaSSL contains minor bug fixes, full session resumption +support, and initial testing suite support. + + + +Please see build instructions in release notes 0.3.0. + + + +******************yaSSL Release notes, version 0.4.0 + +This release of yaSSL contains minor bug fixes, an optional memory tracker, +an echo client and server with input/output redirection for load testing, +and initial session caching support. + + +Please see build instructions in release notes 0.3.0. + + +******************yaSSL Release notes, version 0.3.5 + +This release of yaSSL contains minor bug fixes and extensions to the crypto +library including a full test suite. + + +*******************yaSSL Release notes, version 0.3.0 + +This release of yaSSL contains minor bug fixes and extensions to the crypto +library including AES and an improved random number generator. GNU autoconf +and automake are now used to simplify the build process on Linux. + +*** Linux Build process + +./configure +make + +*** Windows Build process + +open the yassl workspace and build the project + + +*******************yaSSL Release notes, version 0.2.9 + +This release of yaSSL contains minor bug fixes and extensions to the crypto +library. + +See the notes at the bottom of this page for build instructions. + + +*******************yaSSL Release notes, version 0.2.5 + +This release of yaSSL contains minor bug fixes and a beta binary of the yaSSL +libraries for win32 and linux. + +See the notes at the bottom of this page for build instructions. + + + +*******************yaSSL Release notes, version 0.2.0 + +This release of yaSSL contains minor bug fixes and initial alternate crypto +functionality. + +*** Complete Build *** + +See the notes in Readme.txt for build instructions. + +*** Update Build *** + +If you have already done a complete build of yaSSL as described in the release +0.0.1 - 0.1.0 notes and downloaded the update to 0.2.0, place the update file +yassl-update-0.2.0.tar.gz in the yaSSL home directory and issue the command: + +gzip -cd yassl-update-0.2.0.tar.gz | tar xvf - + +to update the previous release. + +Then issue the make command on linux or rebuild the yaSSL project on Windows. + +*******************yaSSL Release notes, version 0.1.0 + +This release of yaSSL contains minor bug fixes, full client and server TLSv1 +support including full ephemeral Diffie-Hellman support, SSL type RSA and DSS +signing and verification, and initial stunnel 4.05 build support. + + + +*********************yaSSL Release notes, version 0.0.3 + +The third release of yaSSL contains minor bug fixes, client certificate +enhancements, and initial ephemeral Diffie-Hellman integration: + + + +********************* + +yaSSL Release notes, version 0.0.2 + +The second release of yaSSL contains minor bug fixes, client certificate +enhancements, session resumption, and improved TLS support including: + +- HMAC for MD5 and SHA-1 +- PRF (pseudo random function) +- Master Secret and Key derivation routines +- Record Authentication codes +- Finish verify data check + +Once ephemeral RSA and DH are added yaSSL will be fully complaint with TLS. + + + +********************** + +yassl Release notes, version 0.0.1 + +The first release of yassl supports normal RSA mode SSLv3 connections with +support for SHA-1 and MD5 digests. Ciphers include DES, 3DES, and RC4. + +yassl uses the CryptoPP library for cryptography, the source is available at +www.cryptopp.com . + +yassl uses CML (the Certificate Management Library) for x509 support. More +features will be in future versions. The CML source is available for download +from www.digitalnet.com/knowledge/cml_home.htm . + +The next release of yassl will support the 3 lesser-used SSL connection modes; +HandShake resumption, Ephemeral RSA (or DH), and Client Authentication as well +as full support for TLS. Backwards support for SSLv2 is not planned at this +time. + + +********************** + +Building yassl on linux: + +use the ./buildall script to build everything. + +buildall will configure and build CML, CryptoPP, and yassl. Testing was +preformed with gcc version 3.3.2 on kernel 2.4.22. + + +********************** + +Building yassl on Windows: + +Testing was preformed on Windows 2000 with Visual C++ 6 sp5. + +1) decompress esnacc_r16.tgz in place, see buildall for syntax if unsure + +2) decompress smp_r23.tgz in place + +3) unzip cryptopp51/crypto51.zip in place + +4) Build SNACC (part of CML) using snacc_builds.dsw in the SNACC directory + +5) Build SMP (part of CMP) using smp.dsw in the smp directory + +6) Build yassl using yassl.dsw + + +********************** + +examples, server and client: + +Please see the server and client examples in both versions to see how to link +to yassl and the support libraries. On linux do 'make server' and 'make +client' to build them. On Windows you will find the example projects in the +main workspace, yassl.dsw. + +The example server and client are compatible with openssl. + + +********************** + +Building yassl into mysql on linux: + +Testing was done using mysql version 4.0.17. + +alter openssl_libs in the configure file, line 21056. Change '-lssl -lcrypto' +to '-lyassl -lcryptopp -lcmapi -lcmlasn -lctil -lc++asn1'. + +see build/config_command for the configure command used to configure mysql +please change /home/touska/ to the relevant directory of course. + +add yassl/lib to the LD_LIBRARY_PATH because libmysql/conf_to_src does not +use the ssl lib directory though it does use the ssl libraries. + +make + +make install + + +********************* + +License: yassl is currently under the GPL, please see license information +in the source and include files. + + +********************* + +Contact: please send comments or questions to Todd A Ouska at todd@yassl.com +and/or Larry Stefonic at larry@yassl.com. + + + diff --git a/mysql/extra/yassl/include/buffer.hpp b/mysql/extra/yassl/include/buffer.hpp new file mode 100644 index 0000000..77d2ed8 --- /dev/null +++ b/mysql/extra/yassl/include/buffer.hpp @@ -0,0 +1,211 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL buffer header defines input and output buffers to simulate streaming + * with SSL types and sockets + */ + +#ifndef yaSSL_BUFFER_HPP +#define yaSSL_BUFFER_HPP + +#include // assert +#include "yassl_types.hpp" // ysDelete +#include "memory.hpp" // mySTL::auto_ptr +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + + +#ifdef _MSC_VER + // disable truncated debug symbols + #pragma warning(disable:4786) +#endif + + +namespace yaSSL { + +typedef unsigned char byte; +typedef unsigned int uint; +const uint AUTO = 0xFEEDBEEF; + + + +struct NoCheck { + int check(uint, uint); +}; + +struct Check { + int check(uint, uint); +}; + +/* input_buffer operates like a smart c style array with a checking option, + * meant to be read from through [] with AUTO index or read(). + * Should only write to at/near construction with assign() or raw (e.g., recv) + * followed by add_size with the number of elements added by raw write. + * + * Not using vector because need checked []access, offset, and the ability to + * write to the buffer bulk wise and have the correct size + */ + +class input_buffer : public Check { + uint size_; // number of elements in buffer + uint current_; // current offset position in buffer + byte* buffer_; // storage for buffer + byte* end_; // end of storage marker + int error_; // error number + byte zero_; // for returning const reference to zero byte +public: + input_buffer(); + + explicit input_buffer(uint s); + + // with assign + input_buffer(uint s, const byte* t, uint len); + + ~input_buffer(); + + // users can pass defualt zero length buffer and then allocate + void allocate(uint s); + + // for passing to raw writing functions at beginning, then use add_size + byte* get_buffer() const; + + // after a raw write user can set new size + // if you know the size before the write use assign() + void add_size(uint i); + + uint get_capacity() const; + + uint get_current() const; + + uint get_size() const; + + uint get_remaining() const; + + int get_error() const; + + void set_error(); + + void set_current(uint i); + + // read only access through [], advance current + // user passes in AUTO index for ease of use + const byte& operator[](uint i); + + // end of input test + bool eof(); + + // peek ahead + byte peek(); + + // write function, should use at/near construction + void assign(const byte* t, uint s); + + // use read to query input, adjusts current + void read(byte* dst, uint length); + +private: + input_buffer(const input_buffer&); // hide copy + input_buffer& operator=(const input_buffer&); // and assign +}; + + +/* output_buffer operates like a smart c style array with a checking option. + * Meant to be written to through [] with AUTO index or write(). + * Size (current) counter increases when written to. Can be constructed with + * zero length buffer but be sure to allocate before first use. + * Don't use add write for a couple bytes, use [] instead, way less overhead. + * + * Not using vector because need checked []access and the ability to + * write to the buffer bulk wise and retain correct size + */ +class output_buffer : public NoCheck { + uint current_; // current offset and elements in buffer + byte* buffer_; // storage for buffer + byte* end_; // end of storage marker +public: + // default + output_buffer(); + + // with allocate + explicit output_buffer(uint s); + + // with assign + output_buffer(uint s, const byte* t, uint len); + + ~output_buffer(); + + uint get_size() const; + + uint get_capacity() const; + + void set_current(uint c); + + // users can pass defualt zero length buffer and then allocate + void allocate(uint s); + + // for passing to reading functions when finished + const byte* get_buffer() const; + + // allow write access through [], update current + // user passes in AUTO as index for ease of use + byte& operator[](uint i); + + // end of output test + bool eof(); + + void write(const byte* t, uint s); + +private: + output_buffer(const output_buffer&); // hide copy + output_buffer& operator=(const output_buffer&); // and assign +}; + + + + +// turn delete an incomplete type into comipler error instead of warning +template +inline void checked_delete(T* p) +{ + typedef char complete_type[sizeof(T) ? 1 : -1]; + (void)sizeof(complete_type); + ysDelete(p); +} + + +// checked delete functor increases effeciency, no indirection on function call +// sets pointer to zero so safe for std conatiners +struct del_ptr_zero +{ + template + void operator()(T*& p) const + { + T* tmp = 0; + STL::swap(tmp, p); + checked_delete(tmp); + } +}; + + + +} // naemspace + +#endif // yaSSL_BUUFER_HPP diff --git a/mysql/extra/yassl/include/cert_wrapper.hpp b/mysql/extra/yassl/include/cert_wrapper.hpp new file mode 100644 index 0000000..8e3393b --- /dev/null +++ b/mysql/extra/yassl/include/cert_wrapper.hpp @@ -0,0 +1,137 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. + */ + + +/* The certificate wrapper header defines certificate management functions + * + */ + + +#ifndef yaSSL_CERT_WRAPPER_HPP +#define yaSSL_CERT_WRAPPER_HPP + +#ifdef _MSC_VER + // disable truncated debug symbols + #pragma warning(disable:4786) +#endif + + +#include "yassl_types.hpp" // SignatureAlgorithm +#include "buffer.hpp" // input_buffer +#include "asn.hpp" // SignerList +#include "openssl/ssl.h" // internal and external use +#include STL_LIST_FILE +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + + +namespace yaSSL { + +typedef unsigned char opaque; +class X509; // forward openSSL type + +using TaoCrypt::SignerList; + +// an x509 version 3 certificate +class x509 { + uint length_; + opaque* buffer_; +public: + explicit x509(uint sz); + ~x509(); + + uint get_length() const; + const opaque* get_buffer() const; + opaque* use_buffer(); + + x509(const x509&); + x509& operator=(const x509&); +private: + void Swap(x509&); +}; + + +// Certificate Manager keeps a list of the cert chain and public key +class CertManager { + typedef STL::list CertList; + + CertList list_; // self + input_buffer privateKey_; + + CertList peerList_; // peer + input_buffer peerPublicKey_; + X509* peerX509_; // peer's openSSL X509 + X509* selfX509_; // our own openSSL X509 + + SignatureAlgorithm keyType_; // self key type + SignatureAlgorithm peerKeyType_; // peer's key type + + SignerList signers_; // decoded CA keys and names + // plus verified chained certs + bool verifyPeer_; + bool verifyNone_; // no error if verify fails + bool failNoCert_; + bool sendVerify_; + bool sendBlankCert_; + VerifyCallback verifyCallback_; // user verify callback +public: + CertManager(); + ~CertManager(); + + void AddPeerCert(x509* x); // take ownership + void CopySelfCert(const x509* x); + int CopyCaCert(const x509* x); + int Validate(); + + int SetPrivateKey(const x509&); + + const x509* get_cert() const; + const opaque* get_peerKey() const; + const opaque* get_privateKey() const; + X509* get_peerX509() const; + X509* get_selfX509() const; + SignatureAlgorithm get_keyType() const; + SignatureAlgorithm get_peerKeyType() const; + + uint get_peerKeyLength() const; + uint get_privateKeyLength() const; + + bool verifyPeer() const; + bool verifyNone() const; + bool failNoCert() const; + bool sendVerify() const; + bool sendBlankCert() const; + + void setVerifyPeer(); + void setVerifyNone(); + void setFailNoCert(); + void setSendVerify(); + void setSendBlankCert(); + void setPeerX509(X509*); + void setVerifyCallback(VerifyCallback); +private: + CertManager(const CertManager&); // hide copy + CertManager& operator=(const CertManager&); // and assigin +}; + + +} // naemspace + +#endif // yaSSL_CERT_WRAPPER_HPP diff --git a/mysql/extra/yassl/include/crypto_wrapper.hpp b/mysql/extra/yassl/include/crypto_wrapper.hpp new file mode 100644 index 0000000..c0395cb --- /dev/null +++ b/mysql/extra/yassl/include/crypto_wrapper.hpp @@ -0,0 +1,428 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* The crypto wrapper header is used to define policies for the cipher + * components used by SSL. There are 3 policies to consider: + * + * 1) MAC, the Message Authentication Code used for each Message + * 2) Bulk Cipher, the Cipher used to encrypt/decrypt each Message + * 3) Atuhentication, the Digitial Signing/Verifiaction scheme used + * + * This header doesn't rely on a specific crypto libraries internals, + * only the implementation should. + */ + + +#ifndef yaSSL_CRYPTO_WRAPPER_HPP +#define yaSSL_CRYPTO_WRAPPER_HPP + +#include "yassl_types.hpp" +#include // FILE + + +namespace yaSSL { + + +// Digest policy should implement a get_digest, update, and get sizes for pad +// and digest +struct Digest : public virtual_base { + virtual void get_digest(byte*) = 0; + virtual void get_digest(byte*, const byte*, unsigned int) = 0; + virtual void update(const byte*, unsigned int) = 0; + virtual uint get_digestSize() const = 0; + virtual uint get_padSize() const = 0; + virtual ~Digest() {} +}; + + +// For use with NULL Digests +struct NO_MAC : public Digest { + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; +}; + + +// MD5 Digest +class MD5 : public Digest { +public: + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; + MD5(); + ~MD5(); + MD5(const MD5&); + MD5& operator=(const MD5&); +private: + struct MD5Impl; + MD5Impl* pimpl_; +}; + + +// SHA-1 Digest +class SHA : public Digest { +public: + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; + SHA(); + ~SHA(); + SHA(const SHA&); + SHA& operator=(const SHA&); +private: + struct SHAImpl; + SHAImpl* pimpl_; + +}; + + +// RIPEMD-160 Digest +class RMD : public Digest { +public: + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; + RMD(); + ~RMD(); + RMD(const RMD&); + RMD& operator=(const RMD&); +private: + struct RMDImpl; + RMDImpl* pimpl_; + +}; + + +// HMAC_MD5 +class HMAC_MD5 : public Digest { +public: + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; + HMAC_MD5(const byte*, unsigned int); + ~HMAC_MD5(); +private: + struct HMAC_MD5Impl; + HMAC_MD5Impl* pimpl_; + + HMAC_MD5(const HMAC_MD5&); + HMAC_MD5& operator=(const HMAC_MD5&); +}; + + +// HMAC_SHA-1 +class HMAC_SHA : public Digest { +public: + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; + HMAC_SHA(const byte*, unsigned int); + ~HMAC_SHA(); +private: + struct HMAC_SHAImpl; + HMAC_SHAImpl* pimpl_; + + HMAC_SHA(const HMAC_SHA&); + HMAC_SHA& operator=(const HMAC_SHA&); +}; + + +// HMAC_RMD +class HMAC_RMD : public Digest { +public: + void get_digest(byte*); + void get_digest(byte*, const byte*, unsigned int); + void update(const byte*, unsigned int); + uint get_digestSize() const; + uint get_padSize() const; + HMAC_RMD(const byte*, unsigned int); + ~HMAC_RMD(); +private: + struct HMAC_RMDImpl; + HMAC_RMDImpl* pimpl_; + + HMAC_RMD(const HMAC_RMD&); + HMAC_RMD& operator=(const HMAC_RMD&); +}; + + +// BulkCipher policy should implement encrypt, decrypt, get block size, +// and set keys for encrypt and decrypt +struct BulkCipher : public virtual_base { + virtual void encrypt(byte*, const byte*, unsigned int) = 0; + virtual void decrypt(byte*, const byte*, unsigned int) = 0; + virtual void set_encryptKey(const byte*, const byte* = 0) = 0; + virtual void set_decryptKey(const byte*, const byte* = 0) = 0; + virtual uint get_blockSize() const = 0; + virtual int get_keySize() const = 0; + virtual int get_ivSize() const = 0; + virtual ~BulkCipher() {} +}; + + +// For use with NULL Ciphers +struct NO_Cipher : public BulkCipher { + void encrypt(byte*, const byte*, unsigned int) {} + void decrypt(byte*, const byte*, unsigned int) {} + void set_encryptKey(const byte*, const byte*) {} + void set_decryptKey(const byte*, const byte*) {} + uint get_blockSize() const { return 0; } + int get_keySize() const { return 0; } + int get_ivSize() const { return 0; } +}; + + +// SSLv3 and TLSv1 always use DES in CBC mode so IV is required +class DES : public BulkCipher { +public: + void encrypt(byte*, const byte*, unsigned int); + void decrypt(byte*, const byte*, unsigned int); + void set_encryptKey(const byte*, const byte*); + void set_decryptKey(const byte*, const byte*); + uint get_blockSize() const { return DES_BLOCK; } + int get_keySize() const { return DES_KEY_SZ; } + int get_ivSize() const { return DES_IV_SZ; } + DES(); + ~DES(); +private: + struct DESImpl; + DESImpl* pimpl_; + + DES(const DES&); // hide copy + DES& operator=(const DES&); // & assign +}; + + +// 3DES Encrypt-Decrypt-Encrypt in CBC mode +class DES_EDE : public BulkCipher { +public: + void encrypt(byte*, const byte*, unsigned int); + void decrypt(byte*, const byte*, unsigned int); + void set_encryptKey(const byte*, const byte*); + void set_decryptKey(const byte*, const byte*); + uint get_blockSize() const { return DES_BLOCK; } + int get_keySize() const { return DES_EDE_KEY_SZ; } + int get_ivSize() const { return DES_IV_SZ; } + DES_EDE(); + ~DES_EDE(); +private: + struct DES_EDEImpl; + DES_EDEImpl* pimpl_; + + DES_EDE(const DES_EDE&); // hide copy + DES_EDE& operator=(const DES_EDE&); // & assign +}; + + +// Alledged RC4 +class RC4 : public BulkCipher { +public: + void encrypt(byte*, const byte*, unsigned int); + void decrypt(byte*, const byte*, unsigned int); + void set_encryptKey(const byte*, const byte*); + void set_decryptKey(const byte*, const byte*); + uint get_blockSize() const { return 0; } + int get_keySize() const { return RC4_KEY_SZ; } + int get_ivSize() const { return 0; } + RC4(); + ~RC4(); +private: + struct RC4Impl; + RC4Impl* pimpl_; + + RC4(const RC4&); // hide copy + RC4& operator=(const RC4&); // & assign +}; + + +// AES +class AES : public BulkCipher { +public: + void encrypt(byte*, const byte*, unsigned int); + void decrypt(byte*, const byte*, unsigned int); + void set_encryptKey(const byte*, const byte*); + void set_decryptKey(const byte*, const byte*); + uint get_blockSize() const { return AES_BLOCK_SZ; } + int get_keySize() const; + int get_ivSize() const { return AES_IV_SZ; } + explicit AES(unsigned int = AES_128_KEY_SZ); + ~AES(); +private: + struct AESImpl; + AESImpl* pimpl_; + + AES(const AES&); // hide copy + AES& operator=(const AES&); // & assign +}; + + +// Random number generator +class RandomPool { +public: + void Fill(opaque* dst, uint sz) const; + RandomPool(); + ~RandomPool(); + + int GetError() const; + + friend class RSA; + friend class DSS; + friend class DiffieHellman; +private: + struct RandomImpl; + RandomImpl* pimpl_; + + RandomPool(const RandomPool&); // hide copy + RandomPool& operator=(const RandomPool&); // & assign +}; + + +// Authentication policy should implement sign, and verify +struct Auth : public virtual_base { + virtual void sign(byte*, const byte*, unsigned int, const RandomPool&) = 0; + virtual bool verify(const byte*, unsigned int, const byte*, + unsigned int) = 0; + virtual uint get_signatureLength() const = 0; + virtual ~Auth() {} +}; + + +// For use with NULL Authentication schemes +struct NO_Auth : public Auth { + void sign(byte*, const byte*, unsigned int, const RandomPool&) {} + bool verify(const byte*, unsigned int, const byte*, unsigned int) + { return true; } +}; + + +// Digitial Signature Standard scheme +class DSS : public Auth { +public: + void sign(byte*, const byte*, unsigned int, const RandomPool&); + bool verify(const byte*, unsigned int, const byte*, unsigned int); + uint get_signatureLength() const; + DSS(const byte*, unsigned int, bool publicKey = true); + ~DSS(); +private: + struct DSSImpl; + DSSImpl* pimpl_; + + DSS(const DSS&); + DSS& operator=(const DSS&); +}; + + +// RSA Authentication and exchange +class RSA : public Auth { +public: + void sign(byte*, const byte*, unsigned int, const RandomPool&); + bool verify(const byte*, unsigned int, const byte*, unsigned int); + void encrypt(byte*, const byte*, unsigned int, const RandomPool&); + void decrypt(byte*, const byte*, unsigned int, const RandomPool&); + uint get_signatureLength() const; + uint get_cipherLength() const; + RSA(const byte*, unsigned int, bool publicKey = true); + ~RSA(); +private: + struct RSAImpl; + RSAImpl* pimpl_; + + RSA(const RSA&); // hide copy + RSA& operator=(const RSA&); // & assing +}; + + +class Integer; + +// Diffie-Hellman agreement +// hide for now TODO: figure out a way to give access to C clients p and g args +class DiffieHellman { +public: + DiffieHellman(const byte*, unsigned int, const byte*, unsigned int, + const byte*, unsigned int, const RandomPool& random); + //DiffieHellman(const char*, const RandomPool&); + DiffieHellman(const Integer&, const Integer&, const RandomPool&); + ~DiffieHellman(); + + DiffieHellman(const DiffieHellman&); + DiffieHellman& operator=(const DiffieHellman&); + + uint get_agreedKeyLength() const; + const byte* get_agreedKey() const; + uint get_publicKeyLength() const; + const byte* get_publicKey() const; + void makeAgreement(const byte*, unsigned int); + + void set_sizes(int&, int&, int&) const; + void get_parms(byte*, byte*, byte*) const; +private: + struct DHImpl; + DHImpl* pimpl_; +}; + + +// Lagrge Integer +class Integer { +public: + Integer(); + ~Integer(); + + Integer(const Integer&); + Integer& operator=(const Integer&); + + void assign(const byte*, unsigned int); + + friend class DiffieHellman; +private: + struct IntegerImpl; + IntegerImpl* pimpl_; +}; + + +class x509; + + +struct EncryptedInfo { + enum { IV_SZ = 32, NAME_SZ = 80 }; + char name[NAME_SZ]; // max one line + byte iv[IV_SZ]; // in base16 rep + uint ivSz; + bool set; + + EncryptedInfo() : ivSz(0), set(false) {} +}; + +x509* PemToDer(FILE*, CertType, EncryptedInfo* info = 0); + + +} // naemspace + +#endif // yaSSL_CRYPTO_WRAPPER_HPP diff --git a/mysql/extra/yassl/include/factory.hpp b/mysql/extra/yassl/include/factory.hpp new file mode 100644 index 0000000..dd6532f --- /dev/null +++ b/mysql/extra/yassl/include/factory.hpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* The factory header defines an Object Factory, used by SSL message and + * handshake types. + * + * See Desgin Pattern in GoF and Alexandrescu's chapter in Modern C++ Design, + * page 208 + */ + + + +#ifndef yaSSL_FACTORY_HPP +#define yaSSL_FACTORY_HPP + +#include STL_VECTOR_FILE +#include STL_PAIR_FILE + + +namespace STL = STL_NAMESPACE; + + + + + +namespace yaSSL { + + +// Factory uses its callback map to create objects by id, +// returning an abstract base pointer +template +class Factory { + typedef STL::pair CallBack; + typedef STL::vector CallBackVector; + + CallBackVector callbacks_; +public: + // pass function pointer to register all callbacks upon creation + explicit Factory(void (*init)(Factory&)) + { + init(*this); + } + + // reserve place in vector before registering, used by init funcion + void Reserve(size_t sz) + { + callbacks_.reserve(sz); + } + + // register callback + void Register(const IdentifierType& id, ProductCreator pc) + { + callbacks_.push_back(STL::make_pair(id, pc)); + } + + // THE Creator, returns a new object of the proper type or 0 + AbstractProduct* CreateObject(const IdentifierType& id) const + { + typedef typename STL::vector::const_iterator cIter; + + cIter first = callbacks_.begin(); + cIter last = callbacks_.end(); + + while (first != last) { + if (first->first == id) + break; + ++first; + } + + if (first == callbacks_.end()) + return 0; + return (first->second)(); + } +private: + Factory(const Factory&); // hide copy + Factory& operator=(const Factory&); // and assign +}; + + +} // naemspace + +#endif // yaSSL_FACTORY_HPP diff --git a/mysql/extra/yassl/include/handshake.hpp b/mysql/extra/yassl/include/handshake.hpp new file mode 100644 index 0000000..0c9949a --- /dev/null +++ b/mysql/extra/yassl/include/handshake.hpp @@ -0,0 +1,69 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* The handshake header declares function prototypes for creating and reading + * the various handshake messages. + */ + + + +#ifndef yaSSL_HANDSHAKE_HPP +#define yaSSL_HANDSHAKE_HPP + +#include "yassl_types.hpp" + + +namespace yaSSL { + +// forward decls +class SSL; +class Finished; +class Data; +class Alert; +struct Hashes; + +enum BufferOutput { buffered, unbuffered }; + +void sendClientHello(SSL&); +void sendServerHello(SSL&, BufferOutput = buffered); +void sendServerHelloDone(SSL&, BufferOutput = buffered); +void sendClientKeyExchange(SSL&, BufferOutput = buffered); +void sendServerKeyExchange(SSL&, BufferOutput = buffered); +void sendChangeCipher(SSL&, BufferOutput = buffered); +void sendFinished(SSL&, ConnectionEnd, BufferOutput = buffered); +void sendCertificate(SSL&, BufferOutput = buffered); +void sendCertificateRequest(SSL&, BufferOutput = buffered); +void sendCertificateVerify(SSL&, BufferOutput = buffered); +int sendData(SSL&, const void*, int); +int sendAlert(SSL& ssl, const Alert& alert); + +int receiveData(SSL&, Data&, bool peek = false); +void processReply(SSL&); + +void buildFinished(SSL&, Finished&, const opaque*); +void build_certHashes(SSL&, Hashes&); + +void hmac(SSL&, byte*, const byte*, uint, ContentType, bool verify = false); +void TLS_hmac(SSL&, byte*, const byte*, uint, ContentType, + bool verify = false); +void PRF(byte* digest, uint digLen, const byte* secret, uint secLen, + const byte* label, uint labLen, const byte* seed, uint seedLen); + +} // naemspace + +#endif // yaSSL_HANDSHAKE_HPP diff --git a/mysql/extra/yassl/include/lock.hpp b/mysql/extra/yassl/include/lock.hpp new file mode 100644 index 0000000..5273f92 --- /dev/null +++ b/mysql/extra/yassl/include/lock.hpp @@ -0,0 +1,96 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* lock.hpp provides an os specific Lock, locks mutex on entry and unlocks + * automatically upon exit, no-ops provided for Single Threaded +*/ + +#ifndef yaSSL_LOCK_HPP +#define yaSSL_LOCK_HPP + +/* + Visual Studio Source Annotations header (sourceannotations.h) fails + to compile if outside of the global namespace. +*/ +#ifdef MULTI_THREADED +#ifdef _WIN32 +#include +#endif +#endif + +namespace yaSSL { + + +#ifdef MULTI_THREADED + #ifdef _WIN32 + #include + + class Mutex { + CRITICAL_SECTION cs_; + public: + Mutex(); + ~Mutex(); + + class Lock; + friend class Lock; + + class Lock { + Mutex& mutex_; + public: + explicit Lock(Mutex& lm); + ~Lock(); + }; + }; + #else // _WIN32 + #include + + class Mutex { + pthread_mutex_t mutex_; + public: + + Mutex(); + ~Mutex(); + + class Lock; + friend class Lock; + + class Lock { + Mutex& mutex_; + public: + explicit Lock(Mutex& lm); + ~Lock(); + }; + }; + + #endif // _WIN32 +#else // MULTI_THREADED (WE'RE SINGLE) + + class Mutex { + public: + class Lock { + public: + explicit Lock(Mutex&) {} + }; + }; + +#endif // MULTI_THREADED + + + +} // namespace +#endif // yaSSL_LOCK_HPP diff --git a/mysql/extra/yassl/include/log.hpp b/mysql/extra/yassl/include/log.hpp new file mode 100644 index 0000000..2651d07 --- /dev/null +++ b/mysql/extra/yassl/include/log.hpp @@ -0,0 +1,55 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL log interface + * + */ + +#ifndef yaSSL_LOG_HPP +#define yaSSL_LOG_HPP + +#include "socket_wrapper.hpp" + +#ifdef YASSL_LOG +#include +#endif + +namespace yaSSL { + +typedef unsigned int uint; + + +// Debug logger +class Log { +#ifdef YASSL_LOG + FILE* log_; +#endif +public: + explicit Log(const char* str = "yaSSL.log"); + ~Log(); + + void Trace(const char*); + void ShowTCP(socket_t, bool ended = false); + void ShowData(uint, bool sent = false); +}; + + +} // naemspace + +#endif // yaSSL_LOG_HPP diff --git a/mysql/extra/yassl/include/openssl/crypto.h b/mysql/extra/yassl/include/openssl/crypto.h new file mode 100644 index 0000000..fc2971a --- /dev/null +++ b/mysql/extra/yassl/include/openssl/crypto.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* crypto.h for openSSL */ + +#ifndef yaSSL_crypto_h__ +#define yaSSL_crypto_h__ + +#ifdef YASSL_PREFIX +#include "prefix_crypto.h" +#endif + +const char* SSLeay_version(int type); + +#define SSLEAY_NUMBER_DEFINED +#define SSLEAY_VERSION 0x0900L +#define SSLEAY_VERSION_NUMBER SSLEAY_VERSION + + +#endif /* yaSSL_crypto_h__ */ + diff --git a/mysql/extra/yassl/include/openssl/des.h b/mysql/extra/yassl/include/openssl/des.h new file mode 100644 index 0000000..f7394b6 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/des.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2005 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* des.h for openssl */ diff --git a/mysql/extra/yassl/include/openssl/des_old.h b/mysql/extra/yassl/include/openssl/des_old.h new file mode 100644 index 0000000..b6e2e3e --- /dev/null +++ b/mysql/extra/yassl/include/openssl/des_old.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2007 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* des_old.h for openvn */ diff --git a/mysql/extra/yassl/include/openssl/engine.h b/mysql/extra/yassl/include/openssl/engine.h new file mode 100644 index 0000000..15ddcd1 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/engine.h @@ -0,0 +1,24 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* engine.h for libcurl */ + +#undef HAVE_OPENSSL_ENGINE_H + + diff --git a/mysql/extra/yassl/include/openssl/err.h b/mysql/extra/yassl/include/openssl/err.h new file mode 100644 index 0000000..9484742 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/err.h @@ -0,0 +1,27 @@ +/* + Copyright (C) 2005, 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* err.h for openssl */ + +#ifndef yaSSL_err_h__ +#define yaSSL_err_h__ + + + +#endif /* yaSSL_err_h__ */ diff --git a/mysql/extra/yassl/include/openssl/evp.h b/mysql/extra/yassl/include/openssl/evp.h new file mode 100644 index 0000000..6aa7335 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/evp.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2007 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* evp.h for openSSL */ + +#ifndef SSLEAY_NUMBER_DEFINED +#define SSLEAY_NUMBER_DEFINED + +/* for OpenVPN */ +#define SSLEAY_VERSION_NUMBER 0x0090700f + + +#endif /* SSLEAY_NUMBER_DEFINED */ diff --git a/mysql/extra/yassl/include/openssl/hmac.h b/mysql/extra/yassl/include/openssl/hmac.h new file mode 100644 index 0000000..5da6644 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/hmac.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2007 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* hmac.h for openvpn */ diff --git a/mysql/extra/yassl/include/openssl/lhash.h b/mysql/extra/yassl/include/openssl/lhash.h new file mode 100644 index 0000000..6d64df7 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/lhash.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2005 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* lhash.h for openSSL */ + diff --git a/mysql/extra/yassl/include/openssl/md4.h b/mysql/extra/yassl/include/openssl/md4.h new file mode 100644 index 0000000..8a86499 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/md4.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* md4.h for libcurl */ diff --git a/mysql/extra/yassl/include/openssl/md5.h b/mysql/extra/yassl/include/openssl/md5.h new file mode 100644 index 0000000..b54ebcd --- /dev/null +++ b/mysql/extra/yassl/include/openssl/md5.h @@ -0,0 +1,23 @@ +/* + Copyright (C) 2005, 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* md5.h for openssl */ + +#include "ssl.h" /* in there for now */ + diff --git a/mysql/extra/yassl/include/openssl/objects.h b/mysql/extra/yassl/include/openssl/objects.h new file mode 100644 index 0000000..ed2c029 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/objects.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2007 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* objects.h for openvpn */ diff --git a/mysql/extra/yassl/include/openssl/opensslv.h b/mysql/extra/yassl/include/openssl/opensslv.h new file mode 100644 index 0000000..88b9ca6 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/opensslv.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2005 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* opensslv.h compatibility */ + +#ifndef yaSSL_opensslv_h__ +#define yaSSL_opensslv_h__ + + +/* api version compatibility */ +#define OPENSSL_VERSION_NUMBER 0x0090700f + + +#endif /* yaSSLopensslv_h__ */ + diff --git a/mysql/extra/yassl/include/openssl/pem.h b/mysql/extra/yassl/include/openssl/pem.h new file mode 100644 index 0000000..c467e46 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/pem.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* pem.h for libcurl */ diff --git a/mysql/extra/yassl/include/openssl/pkcs12.h b/mysql/extra/yassl/include/openssl/pkcs12.h new file mode 100644 index 0000000..c3f8ee6 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/pkcs12.h @@ -0,0 +1,24 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* pkcs12.h for libcurl */ + + +#undef HAVE_OPENSSL_PKCS12_H + diff --git a/mysql/extra/yassl/include/openssl/prefix_crypto.h b/mysql/extra/yassl/include/openssl/prefix_crypto.h new file mode 100644 index 0000000..895dd51 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/prefix_crypto.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#define SSLeay_version yaSSLeay_version diff --git a/mysql/extra/yassl/include/openssl/prefix_ssl.h b/mysql/extra/yassl/include/openssl/prefix_ssl.h new file mode 100644 index 0000000..806f103 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/prefix_ssl.h @@ -0,0 +1,189 @@ +/* + Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#define Copyright yaCopyright +#define yaSSL_CleanUp yayaSSL_CleanUp +#define BN_bin2bn yaBN_bin2bn +#define DH_new yaDH_new +#define DH_free yaDH_free +#define RSA_free yaRSA_free +#define RSA_generate_key yaRSA_generate_key +#define X509_free yaX509_free +#define X509_STORE_CTX_get_current_cert yaX509_STORE_CTX_get_current_cert +#define X509_STORE_CTX_get_error yaX509_STORE_CTX_get_error +#define X509_STORE_CTX_get_error_depth yaX509_STORE_CTX_get_error_depth +#define X509_NAME_oneline yaX509_NAME_oneline +#define X509_get_issuer_name yaX509_get_issuer_name +#define X509_get_subject_name yaX509_get_subject_name +#define X509_verify_cert_error_string yaX509_verify_cert_error_string +#define X509_LOOKUP_add_dir yaX509_LOOKUP_add_dir +#define X509_LOOKUP_load_file yaX509_LOOKUP_load_file +#define X509_LOOKUP_hash_dir yaX509_LOOKUP_hash_dir +#define X509_LOOKUP_file yaX509_LOOKUP_file +#define X509_STORE_add_lookup yaX509_STORE_add_lookup +#define X509_STORE_new yaX509_STORE_new +#define X509_STORE_get_by_subject yaX509_STORE_get_by_subject +#define ERR_get_error_line_data yaERR_get_error_line_data +#define ERR_print_errors_fp yaERR_print_errors_fp +#define ERR_error_string yaERR_error_string +#define ERR_remove_state yaERR_remove_state +#define ERR_get_error yaERR_get_error +#define ERR_peek_error yaERR_peek_error +#define ERR_GET_REASON yaERR_GET_REASON +#define SSL_CTX_new yaSSL_CTX_new +#define SSL_new yaSSL_new +#define SSL_set_fd yaSSL_set_fd +#define SSL_get_fd yaSSL_get_fd +#define SSL_connect yaSSL_connect +#define SSL_write yaSSL_write +#define SSL_read yaSSL_read +#define SSL_accept yaSSL_accept +#define SSL_CTX_free yaSSL_CTX_free +#define SSL_free yaSSL_free +#define SSL_clear yaSSL_clear +#define SSL_shutdown yaSSL_shutdown +#define SSL_set_connect_state yaSSL_set_connect_state +#define SSL_set_accept_state yaSSL_set_accept_state +#define SSL_do_handshake yaSSL_do_handshake +#define SSL_get_cipher yaSSL_get_cipher +#define SSL_get_cipher_name yaSSL_get_cipher_name +#define SSL_get_shared_ciphers yaSSL_get_shared_ciphers +#define SSL_get_cipher_list yaSSL_get_cipher_list +#define SSL_get_version yaSSL_get_version +#define SSLeay_version yaSSLeay_version +#define SSL_get_error yaSSL_get_error +#define SSL_load_error_strings yaSSL_load_error_strings +#define SSL_set_session yaSSL_set_session +#define SSL_get_session yaSSL_get_session +#define SSL_flush_sessions yaSSL_flush_sessions +#define SSL_SESSION_set_timeout yaSSL_SESSION_set_timeout +#define SSL_CTX_set_session_cache_mode yaSSL_CTX_set_session_cache_mode +#define SSL_get_peer_certificate yaSSL_get_peer_certificate +#define SSL_get_verify_result yaSSL_get_verify_result +#define SSL_CTX_set_verify yaSSL_CTX_set_verify +#define SSL_CTX_load_verify_locations yaSSL_CTX_load_verify_locations +#define SSL_CTX_set_default_verify_paths yaSSL_CTX_set_default_verify_paths +#define SSL_CTX_check_private_key yaSSL_CTX_check_private_key +#define SSL_CTX_set_session_id_context yaSSL_CTX_set_session_id_context +#define SSL_CTX_set_tmp_rsa_callback yaSSL_CTX_set_tmp_rsa_callback +#define SSL_CTX_set_options yaSSL_CTX_set_options +#define SSL_CTX_set_session_cache_mode yaSSL_CTX_set_session_cache_mode +#define SSL_CTX_set_timeout yaSSL_CTX_set_timeout +#define SSL_CTX_use_certificate_chain_file yaSSL_CTX_use_certificate_chain_file +#define SSL_CTX_set_default_passwd_cb yaSSL_CTX_set_default_passwd_cb +#define SSL_CTX_use_RSAPrivateKey_file yaSSL_CTX_use_RSAPrivateKey_file +#define SSL_CTX_set_info_callback yaSSL_CTX_set_info_callback +#define SSL_CTX_sess_accept yaSSL_CTX_sess_accept +#define SSL_CTX_sess_connect yaSSL_CTX_sess_connect +#define SSL_CTX_sess_accept_good yaSSL_CTX_sess_accept_good +#define SSL_CTX_sess_connect_good yaSSL_CTX_sess_connect_good +#define SSL_CTX_sess_accept_renegotiate yaSSL_CTX_sess_accept_renegotiate +#define SSL_CTX_sess_connect_renegotiate yaSSL_CTX_sess_connect_renegotiate +#define SSL_CTX_sess_hits yaSSL_CTX_sess_hits +#define SSL_CTX_sess_cb_hits yaSSL_CTX_sess_cb_hits +#define SSL_CTX_sess_cache_full yaSSL_CTX_sess_cache_full +#define SSL_CTX_sess_misses yaSSL_CTX_sess_misses +#define SSL_CTX_sess_timeouts yaSSL_CTX_sess_timeouts +#define SSL_CTX_sess_number yaSSL_CTX_sess_number +#define SSL_CTX_sess_get_cache_size yaSSL_CTX_sess_get_cache_size +#define SSL_CTX_get_verify_mode yaSSL_CTX_get_verify_mode +#define SSL_get_verify_mode yaSSL_get_verify_mode +#define SSL_CTX_get_verify_depth yaSSL_CTX_get_verify_depth +#define SSL_get_verify_depth yaSSL_get_verify_depth +#define SSL_get_default_timeout yaSSL_get_default_timeout +#define SSL_CTX_get_session_cache_mode yaSSL_CTX_get_session_cache_mode +#define SSL_session_reused yaSSL_session_reused +#define SSL_set_rfd yaSSL_set_rfd +#define SSL_set_wfd yaSSL_set_wfd +#define SSL_set_shutdown yaSSL_set_shutdown +#define SSL_set_quiet_shutdown yaSSL_set_quiet_shutdown +#define SSL_get_quiet_shutdown yaSSL_get_quiet_shutdown +#define SSL_want_read yaSSL_want_read +#define SSL_want_write yaSSL_want_write +#define SSL_pending yaSSL_pending +#define SSLv3_method yaSSLv3_method +#define SSLv3_server_method yaSSLv3_server_method +#define SSLv3_client_method yaSSLv3_client_method +#define TLSv1_server_method yaTLSv1_server_method +#define TLSv1_client_method yaTLSv1_client_method +#define TLSv1_1_server_method yaTLSv1_1_server_method +#define TLSv1_1_client_method yaTLSv1_1_client_method +#define SSLv23_server_method yaSSLv23_server_method +#define SSL_CTX_use_certificate_file yaSSL_CTX_use_certificate_file +#define SSL_CTX_use_PrivateKey_file yaSSL_CTX_use_PrivateKey_file +#define SSL_CTX_set_cipher_list yaSSL_CTX_set_cipher_list +#define SSL_CTX_sess_set_cache_size yaSSL_CTX_sess_set_cache_size +#define SSL_CTX_set_tmp_dh yaSSL_CTX_set_tmp_dh +#define OpenSSL_add_all_algorithms yaOpenSSL_add_all_algorithms +#define SSL_library_init yaSSL_library_init +#define SSLeay_add_ssl_algorithms yaSSLeay_add_ssl_algorithms +#define SSL_get_current_cipher yaSSL_get_current_cipher +#define SSL_CIPHER_description yaSSL_CIPHER_description +#define SSL_alert_type_string_long yaSSL_alert_type_string_long +#define SSL_alert_desc_string_long yaSSL_alert_desc_string_long +#define SSL_state_string_long yaSSL_state_string_long +#define EVP_md5 yaEVP_md5 +#define EVP_des_ede3_cbc yaEVP_des_ede3_cbc +#define EVP_BytesToKey yaEVP_BytesToKey +#define DES_set_key_unchecked yaDES_set_key_unchecked +#define DES_ede3_cbc_encrypt yaDES_ede3_cbc_encrypt +#define RAND_screen yaRAND_screen +#define RAND_file_name yaRAND_file_name +#define RAND_write_file yaRAND_write_file +#define RAND_load_file yaRAND_load_file +#define RAND_status yaRAND_status +#define RAND_bytes yaRAND_bytes +#define DES_set_key yaDES_set_key +#define DES_set_odd_parity yaDES_set_odd_parity +#define DES_ecb_encrypt yaDES_ecb_encrypt +#define SSL_CTX_set_default_passwd_cb_userdata yaSSL_CTX_set_default_passwd_cb_userdata +#define SSL_SESSION_free yaSSL_SESSION_free +#define SSL_peek yaSSL_peek +#define SSL_get_certificate yaSSL_get_certificate +#define SSL_get_privatekey yaSSL_get_privatekey +#define X509_get_pubkey yaX509_get_pubkey +#define EVP_PKEY_copy_parameters yaEVP_PKEY_copy_parameters +#define EVP_PKEY_free yaEVP_PKEY_free +#define ERR_error_string_n yaERR_error_string_n +#define ERR_free_strings yaERR_free_strings +#define EVP_cleanup yaEVP_cleanup +#define X509_get_ext_d2i yaX509_get_ext_d2i +#define GENERAL_NAMES_free yaGENERAL_NAMES_free +#define sk_GENERAL_NAME_num yask_GENERAL_NAME_num +#define sk_GENERAL_NAME_value yask_GENERAL_NAME_value +#define ASN1_STRING_data yaASN1_STRING_data +#define ASN1_STRING_length yaASN1_STRING_length +#define ASN1_STRING_type yaASN1_STRING_type +#define X509_NAME_get_index_by_NID yaX509_NAME_get_index_by_NID +#define X509_NAME_ENTRY_get_data yaX509_NAME_ENTRY_get_data +#define X509_NAME_get_entry yaX509_NAME_get_entry +#define ASN1_STRING_to_UTF8 yaASN1_STRING_to_UTF8 +#define SSLv23_client_method yaSSLv23_client_method +#define SSLv2_client_method yaSSLv2_client_method +#define SSL_get1_session yaSSL_get1_session +#define X509_get_notBefore yaX509_get_notBefore +#define X509_get_notAfter yaX509_get_notAfter +#define yaSSL_ASN1_TIME_to_string ya_SSL_ASN1_TIME_to_string +#define MD4_Init yaMD4_Init +#define MD4_Update yaMD4_Update +#define MD4_Final yaMD4_Final +#define MD5_Init yaMD5_Init +#define MD5_Update yaMD5_Update +#define MD5_Final yaMD5_Final +#define SSL_set_compression yaSSL_set_compression +#define PEM_read_X509 yaSSL_PEM_read_X509 diff --git a/mysql/extra/yassl/include/openssl/rand.h b/mysql/extra/yassl/include/openssl/rand.h new file mode 100644 index 0000000..9e0cedf --- /dev/null +++ b/mysql/extra/yassl/include/openssl/rand.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2005 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* rand.h for openSSL */ + diff --git a/mysql/extra/yassl/include/openssl/rsa.h b/mysql/extra/yassl/include/openssl/rsa.h new file mode 100644 index 0000000..95305a8 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/rsa.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2005, 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* rsa.h for openSSL */ + + +#ifndef yaSSL_rsa_h__ +#define yaSSL_rsa_h__ + +enum { RSA_F4 = 1 }; + + +#endif /* yaSSL_rsa_h__ */ diff --git a/mysql/extra/yassl/include/openssl/sha.h b/mysql/extra/yassl/include/openssl/sha.h new file mode 100644 index 0000000..5b7c6bd --- /dev/null +++ b/mysql/extra/yassl/include/openssl/sha.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2007 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* sha.h for openvpn */ diff --git a/mysql/extra/yassl/include/openssl/ssl.h b/mysql/extra/yassl/include/openssl/ssl.h new file mode 100644 index 0000000..10fa491 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/ssl.h @@ -0,0 +1,568 @@ +/* + Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. + */ + +/* ssl.h defines openssl compatibility layer + * + */ + + + +#ifndef yaSSL_openssl_h__ +#define yaSSL_openssl_h__ + +#ifdef YASSL_PREFIX +#include "prefix_ssl.h" +#endif + +#include /* ERR_print fp */ +#include "opensslv.h" /* for version number */ +#include "rsa.h" + + +#define YASSL_VERSION "2.4.4" + + +#if defined(__cplusplus) +extern "C" { +#endif + + void yaSSL_CleanUp(); /* call once at end of application use to + free static singleton memory holders, + not a leak per se, but helpful when + looking for them */ + +#if defined(__cplusplus) +} // extern +#endif + +#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE) +namespace yaSSL { +extern "C" { +#endif + +#undef X509_NAME /* wincrypt.h clash */ + +#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE) + class SSL; + class SSL_SESSION; + class SSL_METHOD; + class SSL_CTX; + class SSL_CIPHER; + + class RSA; + + class X509; + class X509_NAME; +#else + typedef struct SSL SSL; + typedef struct SSL_SESSION SSL_SESSION; + typedef struct SSL_METHOD SSL_METHOD; + typedef struct SSL_CTX SSL_CTX; + typedef struct SSL_CIPHER SSL_CIPHER; + + typedef struct RSA RSA; + + typedef struct X509 X509; + typedef struct X509_NAME X509_NAME; +#endif + + +/* Big Number stuff, different file? */ +typedef struct BIGNUM BIGNUM; + +BIGNUM *BN_bin2bn(const unsigned char*, int, BIGNUM*); + + +/* Diffie-Hellman stuff, different file? */ +/* mySQL deferences to set group parameters */ +typedef struct DH { + BIGNUM* p; + BIGNUM* g; +} DH; + +DH* DH_new(void); +void DH_free(DH*); + +/* RSA stuff */ + +void RSA_free(RSA*); +RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*); + + +/* X509 stuff, different file? */ + +/* because mySQL dereferences to use error and current_cert, even after calling + * get functions for local references */ +typedef struct X509_STORE_CTX { + int error; + int error_depth; + X509* current_cert; +} X509_STORE_CTX; + + +typedef struct X509_STORE X509_STORE; +typedef struct X509_LOOKUP X509_LOOKUP; +typedef struct X509_OBJECT { char c; } X509_OBJECT; +typedef struct X509_CRL X509_CRL; +typedef struct X509_REVOKED X509_REVOKED; +typedef struct X509_LOOKUP_METHOD X509_LOOKUP_METHOD; + + +void X509_free(X509*); + + +/* bio stuff */ +typedef struct BIO BIO; + +/* ASN stuff */ + + + +X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*); +int X509_STORE_CTX_get_error(X509_STORE_CTX*); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*); + +char* X509_NAME_oneline(X509_NAME*, char*, int); +X509_NAME* X509_get_issuer_name(X509*); +X509_NAME* X509_get_subject_name(X509*); +const char* X509_verify_cert_error_string(long); + +int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long); +int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long); +X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void); +X509_LOOKUP_METHOD* X509_LOOKUP_file(void); + +X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*); +X509_STORE* X509_STORE_new(void); +int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, + X509_OBJECT*); + + + + +enum { /* X509 Constants */ + X509_V_OK = 0, + X509_V_ERR_CERT_CHAIN_TOO_LONG = 1, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2, + X509_V_ERR_CERT_NOT_YET_VALID = 3, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 4, + X509_V_ERR_CERT_HAS_EXPIRED = 5, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 6, + X509_FILETYPE_PEM = 7, + X509_LU_X509 = 8, + X509_LU_CRL = 9, + X509_V_ERR_CRL_SIGNATURE_FAILURE = 10, + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 11, + X509_V_ERR_CRL_HAS_EXPIRED = 12, + X509_V_ERR_CERT_REVOKED = 13, + X509_V_FLAG_CRL_CHECK = 14, + X509_V_FLAG_CRL_CHECK_ALL = 15 +}; + + +/* Error stuff, could move to yassl_error */ +unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *); +void ERR_print_errors_fp(FILE*); +char* ERR_error_string(unsigned long,char*); +void ERR_remove_state(unsigned long); +unsigned long ERR_get_error(void); +unsigned long ERR_peek_error(void); +int ERR_GET_REASON(int); + + +enum { /* ERR Constants */ + ERR_TXT_STRING = 1, + EVP_R_BAD_DECRYPT = 2 +}; + +/* + Allow type used by SSL_set_fd to be changed, default to int + in order to be compatible with OpenSSL + */ +#ifndef YASSL_SOCKET_T_DEFINED +typedef int YASSL_SOCKET_T; +#endif + +SSL_CTX* SSL_CTX_new(SSL_METHOD*); +SSL* SSL_new(SSL_CTX*); +int SSL_set_fd (SSL*, YASSL_SOCKET_T); +YASSL_SOCKET_T SSL_get_fd(const SSL*); +int SSL_connect(SSL*); /* if you get an error from connect + see note at top of README */ +int SSL_write(SSL*, const void*, int); +int SSL_read(SSL*, void*, int); +int SSL_accept(SSL*); +void SSL_CTX_free(SSL_CTX*); +void SSL_free(SSL*); +int SSL_clear(SSL*); +int SSL_shutdown(SSL*); + +void SSL_set_connect_state(SSL*); +void SSL_set_accept_state(SSL*); +int SSL_do_handshake(SSL*); + +const char* SSL_get_cipher(SSL*); +const char* SSL_get_cipher_name(SSL*); /* uses SSL_get_cipher */ +char* SSL_get_shared_ciphers(SSL*, char*, int); +const char* SSL_get_cipher_list(SSL*, int); +const char* SSL_get_version(SSL*); +const char* SSLeay_version(int); + +int SSL_get_error(SSL*, int); +void SSL_load_error_strings(void); + +int SSL_set_session(SSL *ssl, SSL_SESSION *session); +SSL_SESSION* SSL_get_session(SSL* ssl); +void SSL_flush_sessions(SSL_CTX *ctx, long tm); +long SSL_SESSION_set_timeout(SSL_SESSION*, long); +long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode); +X509* SSL_get_peer_certificate(SSL*); +long SSL_get_verify_result(SSL*); + + +typedef int (*VerifyCallback)(int, X509_STORE_CTX*); +typedef int (*pem_password_cb)(char*, int, int, void*); +int default_password_callback(char * buffer, int size_arg, int rwflag, + void * u); + +void SSL_CTX_set_verify(SSL_CTX*, int, VerifyCallback verify_callback); +int SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*); +int SSL_CTX_set_default_verify_paths(SSL_CTX*); +int SSL_CTX_check_private_key(SSL_CTX*); +int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*, + unsigned int); + +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int)); +long SSL_CTX_set_options(SSL_CTX*, long); +long SSL_CTX_set_session_cache_mode(SSL_CTX*, long); +long SSL_CTX_set_timeout(SSL_CTX*, long); +int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*); +void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int); +void SSL_CTX_set_info_callback(SSL_CTX*, void (*)()); + +long SSL_CTX_sess_accept(SSL_CTX*); +long SSL_CTX_sess_connect(SSL_CTX*); +long SSL_CTX_sess_accept_good(SSL_CTX*); +long SSL_CTX_sess_connect_good(SSL_CTX*); +long SSL_CTX_sess_accept_renegotiate(SSL_CTX*); +long SSL_CTX_sess_connect_renegotiate(SSL_CTX*); +long SSL_CTX_sess_hits(SSL_CTX*); +long SSL_CTX_sess_cb_hits(SSL_CTX*); +long SSL_CTX_sess_cache_full(SSL_CTX*); +long SSL_CTX_sess_misses(SSL_CTX*); +long SSL_CTX_sess_timeouts(SSL_CTX*); +long SSL_CTX_sess_number(SSL_CTX*); +long SSL_CTX_sess_get_cache_size(SSL_CTX*); + +int SSL_CTX_get_verify_mode(SSL_CTX*); +int SSL_get_verify_mode(SSL*); +int SSL_CTX_get_verify_depth(SSL_CTX*); +int SSL_get_verify_depth(SSL*); + +long SSL_get_default_timeout(SSL*); +long SSL_CTX_get_session_cache_mode(SSL_CTX*); +int SSL_session_reused(SSL*); + +int SSL_set_rfd(SSL*, int); +int SSL_set_wfd(SSL*, int); +void SSL_set_shutdown(SSL*, int); +void SSL_set_quiet_shutdown(SSL *ssl,int mode); +int SSL_get_quiet_shutdown(SSL *ssl); + +int SSL_want_read(SSL*); +int SSL_want_write(SSL*); + +int SSL_pending(SSL*); + + +enum { /* ssl Constants */ + SSL_WOULD_BLOCK = -8, + SSL_BAD_STAT = -7, + SSL_BAD_PATH = -6, + SSL_BAD_FILETYPE = -5, + SSL_BAD_FILE = -4, + SSL_NOT_IMPLEMENTED = -3, + SSL_UNKNOWN = -2, + SSL_FATAL_ERROR = -1, + SSL_NORMAL_SHUTDOWN = 0, + SSL_ERROR_NONE = 0, /* for most functions */ + SSL_FAILURE = 0, /* for some functions */ + SSL_SUCCESS = 1, + + SSL_FILETYPE_ASN1 = 10, + SSL_FILETYPE_PEM = 11, + SSL_FILETYPE_DEFAULT = 10, /* ASN1 */ + + SSL_VERIFY_NONE = 0, + SSL_VERIFY_PEER = 1, + SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2, + SSL_VERIFY_CLIENT_ONCE = 4, + + SSL_SESS_CACHE_OFF = 30, + SSL_SESS_CACHE_CLIENT = 31, + SSL_SESS_CACHE_SERVER = 32, + SSL_SESS_CACHE_BOTH = 33, + SSL_SESS_CACHE_NO_AUTO_CLEAR = 34, + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35, + + SSL_OP_MICROSOFT_SESS_ID_BUG = 50, + SSL_OP_NETSCAPE_CHALLENGE_BUG = 51, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 52, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 53, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 54, + SSL_OP_MSIE_SSLV2_RSA_PADDING = 55, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 56, + SSL_OP_TLS_D5_BUG = 57, + SSL_OP_TLS_BLOCK_PADDING_BUG = 58, + SSL_OP_TLS_ROLLBACK_BUG = 59, + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 60, + SSL_OP_ALL = 61, + SSL_OP_SINGLE_DH_USE = 62, + SSL_OP_EPHEMERAL_RSA = 63, + SSL_OP_PKCS1_CHECK_1 = 67, + SSL_OP_PKCS1_CHECK_2 = 68, + SSL_OP_NETSCAPE_CA_DN_BUG = 69, + SSL_OP_NON_EXPORT_FIRST = 70, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 71, + + SSL_ERROR_WANT_READ = 80, + SSL_ERROR_WANT_WRITE = 81, + SSL_ERROR_SYSCALL = 82, + SSL_ERROR_WANT_X509_LOOKUP = 83, + SSL_ERROR_ZERO_RETURN = 84, + SSL_ERROR_SSL = 85, + + SSL_ST_CONNECT = 90, + SSL_ST_ACCEPT = 91, + SSL_CB_LOOP = 92, + SSL_SENT_SHUTDOWN = 93, + SSL_RECEIVED_SHUTDOWN = 94, + SSL_CB_ALERT = 95, + SSL_CB_READ = 96, + SSL_CB_HANDSHAKE_DONE = 97, + + SSL_OP_NO_SSLv2 = 128, + SSL_OP_NO_SSLv3 = 256, + SSL_OP_NO_TLSv1 = 512, + SSL_OP_NO_TLSv1_1 = 1024, +}; + + +SSL_METHOD *SSLv3_method(void); +SSL_METHOD *SSLv3_server_method(void); +SSL_METHOD *SSLv3_client_method(void); +SSL_METHOD *TLSv1_server_method(void); +SSL_METHOD *TLSv1_client_method(void); +SSL_METHOD *TLSv1_1_server_method(void); +SSL_METHOD *TLSv1_1_client_method(void); +SSL_METHOD *SSLv23_server_method(void); + +int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int); +int SSL_CTX_use_PrivateKey_file(SSL_CTX*, const char*, int); +int SSL_CTX_set_cipher_list(SSL_CTX*, const char*); + +long SSL_CTX_sess_set_cache_size(SSL_CTX*, long); +long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*); + +void OpenSSL_add_all_algorithms(void); +int SSL_library_init(); +int SSLeay_add_ssl_algorithms(void); + + +SSL_CIPHER* SSL_get_current_cipher(SSL*); +char* SSL_CIPHER_description(SSL_CIPHER*, char*, int); + + +char* SSL_alert_type_string_long(int); +char* SSL_alert_desc_string_long(int); +char* SSL_state_string_long(SSL*); + +X509* PEM_read_X509(FILE *fp, X509 *x, pem_password_cb cb, void *u); +/* EVP stuff, des and md5, different file? */ +typedef char EVP_MD; + +typedef char EVP_CIPHER; + +typedef struct EVP_PKEY EVP_PKEY; + +typedef unsigned char DES_cblock[8]; +typedef const DES_cblock const_DES_cblock; +typedef DES_cblock DES_key_schedule; + +enum { + DES_ENCRYPT = 1, + DES_DECRYPT = 0 +}; + +const EVP_MD* EVP_md5(void); +const EVP_CIPHER* EVP_des_ede3_cbc(void); + +typedef unsigned char opaque; + +int EVP_BytesToKey(const EVP_CIPHER*, const EVP_MD*, const opaque*, + const opaque*, int, int, opaque*, opaque*); + +void DES_set_key_unchecked(const_DES_cblock*, DES_key_schedule*); +void DES_ede3_cbc_encrypt(const opaque*, opaque*, long, DES_key_schedule*, + DES_key_schedule*, DES_key_schedule*, DES_cblock*, int); + + +/* RAND stuff */ +void RAND_screen(void); +const char* RAND_file_name(char*, size_t); +int RAND_write_file(const char*); +int RAND_load_file(const char*, long); + + +/* for libcurl */ +int RAND_status(void); +int RAND_bytes(unsigned char* buf, int num); + +int DES_set_key(const_DES_cblock*, DES_key_schedule*); +void DES_set_odd_parity(DES_cblock*); +void DES_ecb_encrypt(DES_cblock*, DES_cblock*, DES_key_schedule*, int); + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata); +void SSL_SESSION_free(SSL_SESSION* session); +int SSL_peek(SSL* ssl, void* buf, int num); + +X509* SSL_get_certificate(SSL* ssl); +EVP_PKEY* SSL_get_privatekey(SSL* ssl); +EVP_PKEY* X509_get_pubkey(X509* x); + +int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from); +void EVP_PKEY_free(EVP_PKEY* pkey); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +void ERR_free_strings(void); +void EVP_cleanup(void); + +void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx); + +#define GEN_IPADD 7 +#define NID_subject_alt_name 85 +#define STACK_OF(x) x + + +/* defined here because libcurl dereferences */ +typedef struct ASN1_STRING { + int type; + int length; + unsigned char* data; +} ASN1_STRING; + + +typedef struct GENERAL_NAME { + int type; + union { + ASN1_STRING* ia5; + } d; +} GENERAL_NAME; + +void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x); + +int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x); +GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i); + + +unsigned char* ASN1_STRING_data(ASN1_STRING* x); +int ASN1_STRING_length(ASN1_STRING* x); +int ASN1_STRING_type(ASN1_STRING *x); + +typedef ASN1_STRING X509_NAME_ENTRY; + +int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos); + +ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne); +X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc); + +#define OPENSSL_malloc(x) malloc(x) +#define OPENSSL_free(x) free(x) + +int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in); + +SSL_METHOD* SSLv23_client_method(void); /* doesn't actually roll back */ +SSL_METHOD* SSLv2_client_method(void); /* will never work, no v 2 */ + + +SSL_SESSION* SSL_get1_session(SSL* ssl); /* what's ref count */ + + +#define CRYPTO_free(x) free(x) +#define ASN1_TIME ASN1_STRING + +ASN1_TIME* X509_get_notBefore(X509* x); +ASN1_TIME* X509_get_notAfter(X509* x); + + +#define ASN1_UTCTIME ASN1_STRING +#define NID_commonName 13 +#define V_ASN1_UTF8STRING 12 +#define GEN_DNS 2 + +#define CERTFICATE_ERROR 0x14090086 /* SSLv3 error */ + + +typedef struct MD4_CTX { + int buffer[32]; /* big enough to hold, check size in Init */ +} MD4_CTX; + +void MD4_Init(MD4_CTX*); +void MD4_Update(MD4_CTX*, const void*, unsigned long); +void MD4_Final(unsigned char*, MD4_CTX*); + + +typedef struct MD5_CTX { + int buffer[32]; /* big enough to hold, check size in Init */ +} MD5_CTX; + +void MD5_Init(MD5_CTX*); +void MD5_Update(MD5_CTX*, const void*, unsigned long); +void MD5_Final(unsigned char*, MD5_CTX*); + +#define MD5_DIGEST_LENGTH 16 + + +#define SSL_DEFAULT_CIPHER_LIST "" /* default all */ + + +/* yaSSL extensions */ +int SSL_set_compression(SSL*); /* turn on yaSSL zlib compression */ +char *yaSSL_ASN1_TIME_to_string(ASN1_TIME *time, char *buf, size_t len); + +#include "transport_types.h" + +/* + Set functions for yaSSL to use in order to send and receive data. + + These hooks are offered in order to enable non-blocking I/O. If + not set, yaSSL defaults to using send() and recv(). + + @todo Remove hooks and accompanying code when yaSSL is fixed. +*/ +void yaSSL_transport_set_ptr(SSL *, void *); +void yaSSL_transport_set_recv_function(SSL *, yaSSL_recv_func_t); +void yaSSL_transport_set_send_function(SSL *, yaSSL_send_func_t); + +#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE) +} /* namespace */ +} /* extern "C" */ +#endif + + +#endif /* yaSSL_openssl_h__ */ diff --git a/mysql/extra/yassl/include/openssl/transport_types.h b/mysql/extra/yassl/include/openssl/transport_types.h new file mode 100644 index 0000000..5a9d234 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/transport_types.h @@ -0,0 +1,26 @@ +/* + Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef yaSSL_transport_types_h__ +#define yaSSL_transport_types_h__ + +/* Type of transport functions used for sending and receiving data. */ +typedef long (*yaSSL_recv_func_t) (void *, void *, size_t); +typedef long (*yaSSL_send_func_t) (void *, const void *, size_t); + +#endif diff --git a/mysql/extra/yassl/include/openssl/x509.h b/mysql/extra/yassl/include/openssl/x509.h new file mode 100644 index 0000000..74eb83e --- /dev/null +++ b/mysql/extra/yassl/include/openssl/x509.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* x509.h for libcurl */ diff --git a/mysql/extra/yassl/include/openssl/x509v3.h b/mysql/extra/yassl/include/openssl/x509v3.h new file mode 100644 index 0000000..b48e9b4 --- /dev/null +++ b/mysql/extra/yassl/include/openssl/x509v3.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2006 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* x509v3.h for libcurl */ diff --git a/mysql/extra/yassl/include/socket_wrapper.hpp b/mysql/extra/yassl/include/socket_wrapper.hpp new file mode 100644 index 0000000..ec3ab6f --- /dev/null +++ b/mysql/extra/yassl/include/socket_wrapper.hpp @@ -0,0 +1,104 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. + */ + + +/* The socket wrapper header defines a Socket class that hides the differences + * between Berkely style sockets and Windows sockets, allowing transparent TCP + * access. + */ + + +#ifndef yaSSL_SOCKET_WRAPPER_HPP +#define yaSSL_SOCKET_WRAPPER_HPP + + +#ifdef _WIN32 + #include +#else + #include + #include + #include + #include + #include + #include +#endif + + +namespace yaSSL { + +typedef unsigned int uint; + +#ifdef _WIN32 + typedef SOCKET socket_t; +#else + typedef int socket_t; + const socket_t INVALID_SOCKET = -1; + const int SD_RECEIVE = 0; + const int SD_SEND = 1; + const int SD_BOTH = 2; + const int SOCKET_ERROR = -1; +#endif + + extern "C" { + #include "openssl/transport_types.h" + } + +typedef unsigned char byte; + + +// Wraps Windows Sockets and BSD Sockets +class Socket { + socket_t socket_; // underlying socket descriptor + bool wouldBlock_; // if non-blocking data, for last read + bool nonBlocking_; // is option set + void *ptr_; // Argument to transport function + yaSSL_send_func_t send_func_; // Function to send data + yaSSL_recv_func_t recv_func_; // Function to receive data +public: + explicit Socket(socket_t s = INVALID_SOCKET); + ~Socket(); + + void set_fd(socket_t s); + uint get_ready() const; + socket_t get_fd() const; + + void set_transport_ptr(void *ptr); + void set_transport_recv_function(yaSSL_recv_func_t recv_func); + void set_transport_send_function(yaSSL_send_func_t send_func); + + uint send(const byte* buf, unsigned int len, unsigned int& sent); + uint receive(byte* buf, unsigned int len); + + bool wait(); + bool WouldBlock() const; + bool IsNonBlocking() const; + + void closeSocket(); + void shutDown(int how = SD_SEND); + + static int get_lastError(); + static void set_lastError(int error); +private: + Socket(const Socket&); // hide copy + Socket& operator= (const Socket&); // and assign +}; + + +} // naemspace + +#endif // yaSSL_SOCKET_WRAPPER_HPP diff --git a/mysql/extra/yassl/include/timer.hpp b/mysql/extra/yassl/include/timer.hpp new file mode 100644 index 0000000..0d99603 --- /dev/null +++ b/mysql/extra/yassl/include/timer.hpp @@ -0,0 +1,40 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* timer.hpp provides a high res and low res timers + * +*/ + + +#ifndef yaSSL_TIMER_HPP +#define yaSSL_TIMER_HPP + +namespace yaSSL { + +typedef double timer_d; +typedef unsigned int uint; + + + +timer_d timer(); +uint lowResTimer(); + + + +} // namespace +#endif // yaSSL_TIMER_HPP diff --git a/mysql/extra/yassl/include/yassl.hpp b/mysql/extra/yassl/include/yassl.hpp new file mode 100644 index 0000000..081d653 --- /dev/null +++ b/mysql/extra/yassl/include/yassl.hpp @@ -0,0 +1,85 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL externel header defines yaSSL API + */ + + +#ifndef yaSSL_EXT_HPP +#define yaSSL_EXT_HPP + + +namespace yaSSL { + + +#ifdef _WIN32 + typedef unsigned int SOCKET_T; +#else + typedef int SOCKET_T; +#endif + + +class Client { +public: + Client(); + ~Client(); + + // basics + int Connect(SOCKET_T); + int Write(const void*, int); + int Read(void*, int); + + // options + void SetCA(const char*); + void SetCert(const char*); + void SetKey(const char*); +private: + struct ClientImpl; + ClientImpl* pimpl_; + + Client(const Client&); // hide copy + Client& operator=(const Client&); // and assign +}; + + +class Server { +public: + Server(); + ~Server(); + + // basics + int Accept(SOCKET_T); + int Write(const void*, int); + int Read(void*, int); + + // options + void SetCA(const char*); + void SetCert(const char*); + void SetKey(const char*); +private: + struct ServerImpl; + ServerImpl* pimpl_; + + Server(const Server&); // hide copy + Server& operator=(const Server&); // and assign +}; + + +} // namespace yaSSL +#endif // yaSSL_EXT_HPP diff --git a/mysql/extra/yassl/include/yassl_error.hpp b/mysql/extra/yassl/include/yassl_error.hpp new file mode 100644 index 0000000..d63244d --- /dev/null +++ b/mysql/extra/yassl/include/yassl_error.hpp @@ -0,0 +1,88 @@ +/* + Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL error header defines error codes and an exception class + */ + +#ifndef yaSSL_ERROR_HPP +#define yaSSL_ERROR_HPP + + + +namespace yaSSL { + + +enum YasslError { + no_error = 0, + + // 10 - 47 from AlertDescription, 0 also close_notify + + range_error = 101, + realloc_error = 102, + factory_error = 103, + unknown_cipher = 104, + prefix_error = 105, + record_layer = 106, + handshake_layer = 107, + out_of_order = 108, + bad_input = 109, + match_error = 110, + no_key_file = 111, + verify_error = 112, + send_error = 113, + receive_error = 114, + certificate_error = 115, + privateKey_error = 116, + badVersion_error = 117, + compress_error = 118, + decompress_error = 119, + pms_version_error = 120, + sanityCipher_error = 121, + rsaSignFault_error = 122 + + // !!!! add error message to .cpp !!!! + + // 1000+ from TaoCrypt error.hpp + +}; + + +enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib }; +enum { MAX_ERROR_SZ = 80 }; + +void SetErrorString(YasslError, char*); + +/* remove for now, if go back to exceptions use this wrapper +// Base class for all yaSSL exceptions +class Error : public mySTL::runtime_error { + YasslError error_; + Library lib_; +public: + explicit Error(const char* s = "", YasslError e = no_error, + Library l = yaSSL_Lib); + + YasslError get_number() const; + Library get_lib() const; +}; +*/ + + +} // naemspace + +#endif // yaSSL_ERROR_HPP diff --git a/mysql/extra/yassl/include/yassl_imp.hpp b/mysql/extra/yassl/include/yassl_imp.hpp new file mode 100644 index 0000000..a952da0 --- /dev/null +++ b/mysql/extra/yassl/include/yassl_imp.hpp @@ -0,0 +1,748 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* yaSSL implementation header defines all strucutres from the SSL.v3 + * specification "draft-freier-ssl-version3-02.txt" + * all page citations refer to this document unless otherwise noted. + */ + + +#ifndef yaSSL_IMP_HPP +#define yaSSL_IMP_HPP + +#ifdef _MSC_VER + // disable truncated debug symbols + #pragma warning(disable:4786) +#endif + +#include "yassl_types.hpp" +#include "factory.hpp" +#include STL_LIST_FILE + + +namespace STL = STL_NAMESPACE; + + +namespace yaSSL { + + +class SSL; // forward decls +class input_buffer; +class output_buffer; + + +struct ProtocolVersion { + uint8 major_; + uint8 minor_; // major and minor SSL/TLS version numbers + + ProtocolVersion(uint8 maj = 3, uint8 min = 0); +}; + + +// Record Layer Header for PlainText, Compressed, and CipherText +struct RecordLayerHeader { + ContentType type_; + ProtocolVersion version_; + uint16 length_; // should not exceed 2^14 +}; + + +// base for all messages +struct Message : public virtual_base { + virtual input_buffer& set(input_buffer&) =0; + virtual output_buffer& get(output_buffer&) const =0; + + virtual void Process(input_buffer&, SSL&) =0; + virtual ContentType get_type() const =0; + virtual uint16 get_length() const =0; + + virtual ~Message() {} +}; + + +class ChangeCipherSpec : public Message { + CipherChoice type_; +public: + ChangeCipherSpec(); + + friend input_buffer& operator>>(input_buffer&, ChangeCipherSpec&); + friend output_buffer& operator<<(output_buffer&, const ChangeCipherSpec&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + ContentType get_type() const; + uint16 get_length() const; + void Process(input_buffer&, SSL&); +private: + ChangeCipherSpec(const ChangeCipherSpec&); // hide copy + ChangeCipherSpec& operator=(const ChangeCipherSpec&); // and assign +}; + + + +class Alert : public Message { + AlertLevel level_; + AlertDescription description_; +public: + Alert() {} + Alert(AlertLevel al, AlertDescription ad); + + ContentType get_type() const; + uint16 get_length() const; + void Process(input_buffer&, SSL&); + + friend input_buffer& operator>>(input_buffer&, Alert&); + friend output_buffer& operator<<(output_buffer&, const Alert&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; +private: + Alert(const Alert&); // hide copy + Alert& operator=(const Alert&); // and assign +}; + + +class Data : public Message { + uint16 length_; + opaque* buffer_; // read buffer used by fillData input + const opaque* write_buffer_; // write buffer used by output operator +public: + Data(); + Data(uint16 len, opaque* b); + + friend output_buffer& operator<<(output_buffer&, const Data&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + ContentType get_type() const; + uint16 get_length() const; + void set_length(uint16 l); + opaque* set_buffer(); + void SetData(uint16, const opaque*); + void Process(input_buffer&, SSL&); +private: + Data(const Data&); // hide copy + Data& operator=(const Data&); // and assign +}; + + +uint32 c24to32(const uint24); // forward form internal header +void c32to24(uint32, uint24&); + + +// HandShake header, same for each message type from page 20/21 +class HandShakeHeader : public Message { + HandShakeType type_; + uint24 length_; // length of message +public: + HandShakeHeader() {} + + ContentType get_type() const; + uint16 get_length() const; + HandShakeType get_handshakeType() const; + void Process(input_buffer&, SSL&); + + void set_type(HandShakeType hst); + void set_length(uint32 u32); + + friend input_buffer& operator>>(input_buffer&, HandShakeHeader&); + friend output_buffer& operator<<(output_buffer&, const HandShakeHeader&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; +private: + HandShakeHeader(const HandShakeHeader&); // hide copy + HandShakeHeader& operator=(const HandShakeHeader&); // and assign +}; + + +// Base Class for all handshake messages +class HandShakeBase : public virtual_base { + int length_; +public: + int get_length() const; + void set_length(int); + + // for building buffer's type field + virtual HandShakeType get_type() const =0; + + // handles dispactch of proper >> + virtual input_buffer& set(input_buffer& in) =0; + virtual output_buffer& get(output_buffer& out) const =0; + + virtual void Process(input_buffer&, SSL&) =0; + + virtual ~HandShakeBase() {} +}; + + +struct HelloRequest : public HandShakeBase { + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + void Process(input_buffer&, SSL&); + + HandShakeType get_type() const; +}; + + +// The Client's Hello Message from page 23 +class ClientHello : public HandShakeBase { + ProtocolVersion client_version_; + Random random_; + uint8 id_len_; // session id length + opaque session_id_[ID_LEN]; + uint16 suite_len_; // cipher suite length + opaque cipher_suites_[MAX_SUITE_SZ]; + uint8 comp_len_; // compression length + CompressionMethod compression_methods_; +public: + friend input_buffer& operator>>(input_buffer&, ClientHello&); + friend output_buffer& operator<<(output_buffer&, const ClientHello&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + HandShakeType get_type() const; + void Process(input_buffer&, SSL&); + + const opaque* get_random() const; + friend void buildClientHello(SSL&, ClientHello&); + friend void ProcessOldClientHello(input_buffer& input, SSL& ssl); + + ClientHello(); + ClientHello(ProtocolVersion pv, bool useCompression); +private: + ClientHello(const ClientHello&); // hide copy + ClientHello& operator=(const ClientHello&); // and assign +}; + + + +// The Server's Hello Message from page 24 +class ServerHello : public HandShakeBase { + ProtocolVersion server_version_; + Random random_; + uint8 id_len_; // session id length + opaque session_id_[ID_LEN]; + opaque cipher_suite_[SUITE_LEN]; + CompressionMethod compression_method_; +public: + ServerHello(ProtocolVersion pv, bool useCompression); + ServerHello(); + + friend input_buffer& operator>>(input_buffer&, ServerHello&); + friend output_buffer& operator<<(output_buffer&, const ServerHello&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + HandShakeType get_type() const; + void Process(input_buffer&, SSL&); + + const opaque* get_random() const; + friend void buildServerHello(SSL&, ServerHello&); +private: + ServerHello(const ServerHello&); // hide copy + ServerHello& operator=(const ServerHello&); // and assign +}; + + +class x509; + +// Certificate could be a chain +class Certificate : public HandShakeBase { + const x509* cert_; +public: + Certificate(); + explicit Certificate(const x509* cert); + friend output_buffer& operator<<(output_buffer&, const Certificate&); + + const opaque* get_buffer() const; + + // Process handles input, needs SSL + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + HandShakeType get_type() const; + void Process(input_buffer&, SSL&); +private: + Certificate(const Certificate&); // hide copy + Certificate& operator=(const Certificate&); // and assign +}; + + + +// RSA Public Key +struct ServerRSAParams { + opaque* rsa_modulus_; + opaque* rsa_exponent_; +}; + + +// Ephemeral Diffie-Hellman Parameters +class ServerDHParams { + int pSz_; + int gSz_; + int pubSz_; + opaque* p_; + opaque* g_; + opaque* Ys_; +public: + ServerDHParams(); + ~ServerDHParams(); + + int get_pSize() const; + int get_gSize() const; + int get_pubSize() const; + + const opaque* get_p() const; + const opaque* get_g() const; + const opaque* get_pub() const; + + opaque* alloc_p(int sz); + opaque* alloc_g(int sz); + opaque* alloc_pub(int sz); +private: + ServerDHParams(const ServerDHParams&); // hide copy + ServerDHParams& operator=(const ServerDHParams&); // and assign +}; + + +struct ServerKeyBase : public virtual_base { + virtual ~ServerKeyBase() {} + virtual void build(SSL&) {} + virtual void read(SSL&, input_buffer&) {} + virtual int get_length() const; + virtual opaque* get_serverKey() const; +}; + + +// Server random number for FORTEZZA KEA +struct Fortezza_Server : public ServerKeyBase { + opaque r_s_[FORTEZZA_MAX]; +}; + + +struct SignatureBase : public virtual_base { + virtual ~SignatureBase() {} +}; + +struct anonymous_sa : public SignatureBase {}; + + +struct Hashes { + uint8 md5_[MD5_LEN]; + uint8 sha_[SHA_LEN]; +}; + + +struct rsa_sa : public SignatureBase { + Hashes hashes_; +}; + + +struct dsa_sa : public SignatureBase { + uint8 sha_[SHA_LEN]; +}; + + +// Server's Diffie-Hellman exchange +class DH_Server : public ServerKeyBase { + ServerDHParams parms_; + opaque* signature_; + + int length_; // total length of message + opaque* keyMessage_; // total exchange message +public: + DH_Server(); + ~DH_Server(); + + void build(SSL&); + void read(SSL&, input_buffer&); + int get_length() const; + opaque* get_serverKey() const; +private: + DH_Server(const DH_Server&); // hide copy + DH_Server& operator=(const DH_Server&); // and assign +}; + + +// Server's RSA exchange +struct RSA_Server : public ServerKeyBase { + ServerRSAParams params_; + opaque* signature_; // signed rsa_sa hashes +}; + + +class ServerKeyExchange : public HandShakeBase { + ServerKeyBase* server_key_; +public: + explicit ServerKeyExchange(SSL&); + ServerKeyExchange(); + ~ServerKeyExchange(); + + void createKey(SSL&); + void build(SSL& ssl); + + const opaque* getKey() const; + int getKeyLength() const; + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + friend output_buffer& operator<<(output_buffer&, const ServerKeyExchange&); + + void Process(input_buffer&, SSL&); + HandShakeType get_type() const; +private: + ServerKeyExchange(const ServerKeyExchange&); // hide copy + ServerKeyExchange& operator=(const ServerKeyExchange&); // and assign +}; + + + +class CertificateRequest : public HandShakeBase { + ClientCertificateType certificate_types_[CERT_TYPES]; + int typeTotal_; + STL::list certificate_authorities_; +public: + CertificateRequest(); + ~CertificateRequest(); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + friend input_buffer& operator>>(input_buffer&, CertificateRequest&); + friend output_buffer& operator<<(output_buffer&, + const CertificateRequest&); + + void Process(input_buffer&, SSL&); + HandShakeType get_type() const; + + void Build(); +private: + CertificateRequest(const CertificateRequest&); // hide copy + CertificateRequest& operator=(const CertificateRequest&); // and assign +}; + + +struct ServerHelloDone : public HandShakeBase { + ServerHelloDone(); + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + void Process(input_buffer& input, SSL& ssl); + + HandShakeType get_type() const; +}; + + +struct PreMasterSecret { + opaque random_[SECRET_LEN]; // first two bytes Protocol Version +}; + + +struct ClientKeyBase : public virtual_base { + virtual ~ClientKeyBase() {} + virtual void build(SSL&) {} + virtual void read(SSL&, input_buffer&) {} + virtual int get_length() const; + virtual opaque* get_clientKey() const; +}; + + +class EncryptedPreMasterSecret : public ClientKeyBase { + opaque* secret_; + int length_; +public: + EncryptedPreMasterSecret(); + ~EncryptedPreMasterSecret(); + + void build(SSL&); + void read(SSL&, input_buffer&); + int get_length() const; + opaque* get_clientKey() const; + void alloc(int sz); +private: + // hide copy and assign + EncryptedPreMasterSecret(const EncryptedPreMasterSecret&); + EncryptedPreMasterSecret& operator=(const EncryptedPreMasterSecret&); +}; + + +// Fortezza Key Parameters from page 29 +// hard code lengths cause only used here +struct FortezzaKeys : public ClientKeyBase { + opaque y_c_ [128]; // client's Yc, public value + opaque r_c_ [128]; // client's Rc + opaque y_signature_ [40]; // DSS signed public key + opaque wrapped_client_write_key_ [12]; // wrapped by the TEK + opaque wrapped_server_write_key_ [12]; // wrapped by the TEK + opaque client_write_iv_ [24]; + opaque server_write_iv_ [24]; + opaque master_secret_iv_ [24]; // IV used to encrypt preMaster + opaque encrypted_preMasterSecret_[48]; // random & crypted by the TEK +}; + + + +// Diffie-Hellman public key from page 40/41 +class ClientDiffieHellmanPublic : public ClientKeyBase { + PublicValueEncoding public_value_encoding_; + int length_; // includes two byte length for message + opaque* Yc_; // length + Yc_ + // dh_Yc only if explicit, otherwise sent in certificate + enum { KEY_OFFSET = 2 }; +public: + ClientDiffieHellmanPublic(); + ~ClientDiffieHellmanPublic(); + + void build(SSL&); + void read(SSL&, input_buffer&); + int get_length() const; + opaque* get_clientKey() const; + void alloc(int sz, bool offset = false); +private: + // hide copy and assign + ClientDiffieHellmanPublic(const ClientDiffieHellmanPublic&); + ClientDiffieHellmanPublic& operator=(const ClientDiffieHellmanPublic&); +}; + + +class ClientKeyExchange : public HandShakeBase { + ClientKeyBase* client_key_; +public: + explicit ClientKeyExchange(SSL& ssl); + ClientKeyExchange(); + ~ClientKeyExchange(); + + void createKey(SSL&); + void build(SSL& ssl); + + const opaque* getKey() const; + int getKeyLength() const; + + friend output_buffer& operator<<(output_buffer&, const ClientKeyExchange&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + HandShakeType get_type() const; + void Process(input_buffer&, SSL&); +private: + ClientKeyExchange(const ClientKeyExchange&); // hide copy + ClientKeyExchange& operator=(const ClientKeyExchange&); // and assign +}; + + +class CertificateVerify : public HandShakeBase { + Hashes hashes_; + byte* signature_; // owns +public: + CertificateVerify(); + ~CertificateVerify(); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + friend input_buffer& operator>>(input_buffer&, CertificateVerify&); + friend output_buffer& operator<<(output_buffer&, const CertificateVerify&); + + void Process(input_buffer&, SSL&); + HandShakeType get_type() const; + + void Build(SSL&); +private: + CertificateVerify(const CertificateVerify&); // hide copy + CertificateVerify& operator=(const CertificateVerify&); // and assign +}; + + +class Finished : public HandShakeBase { + Hashes hashes_; +public: + Finished(); + + uint8* set_md5(); + uint8* set_sha(); + + friend input_buffer& operator>>(input_buffer&, Finished&); + friend output_buffer& operator<<(output_buffer&, const Finished&); + + input_buffer& set(input_buffer& in); + output_buffer& get(output_buffer& out) const; + + void Process(input_buffer&, SSL&); + + HandShakeType get_type() const; +private: + Finished(const Finished&); // hide copy + Finished& operator=(const Finished&); // and assign +}; + + +class RandomPool; // forward for connection + + +// SSL Connection defined on page 11 +struct Connection { + opaque *pre_master_secret_; + opaque master_secret_[SECRET_LEN]; + opaque client_random_[RAN_LEN]; + opaque server_random_[RAN_LEN]; + opaque sessionID_[ID_LEN]; + opaque client_write_MAC_secret_[SHA_LEN]; // sha is max size + opaque server_write_MAC_secret_[SHA_LEN]; + opaque client_write_key_[AES_256_KEY_SZ]; // aes 256bit is max sz + opaque server_write_key_[AES_256_KEY_SZ]; + opaque client_write_IV_[AES_IV_SZ]; // aes is max size + opaque server_write_IV_[AES_IV_SZ]; + uint32 sequence_number_; + uint32 peer_sequence_number_; + uint32 pre_secret_len_; // pre master length + bool send_server_key_; // server key exchange? + bool master_clean_; // master secret clean? + bool TLS_; // TLSv1 or greater + bool TLSv1_1_; // TLSv1.1 or greater + bool sessionID_Set_; // do we have a session + bool compression_; // zlib compression? + ProtocolVersion version_; // negotiated version + ProtocolVersion chVersion_; // client hello version + RandomPool& random_; + + Connection(ProtocolVersion v, RandomPool& ran); + ~Connection(); + + void AllocPreSecret(uint sz); + void CleanPreMaster(); + void CleanMaster(); + void TurnOffTLS(); + void TurnOffTLS1_1(); +private: + Connection(const Connection&); // hide copy + Connection& operator=(const Connection&); // and assign +}; + + +struct Ciphers; // forward + + +// TLSv1 Security Spec, defined on page 56 of RFC 2246 +struct Parameters { + ConnectionEnd entity_; + BulkCipherAlgorithm bulk_cipher_algorithm_; + CipherType cipher_type_; + uint8 key_size_; + uint8 iv_size_; + IsExportable is_exportable_; + MACAlgorithm mac_algorithm_; + uint8 hash_size_; + CompressionMethod compression_algorithm_; + KeyExchangeAlgorithm kea_; // yassl additions + SignatureAlgorithm sig_algo_; // signature auth type + SignatureAlgorithm verify_algo_; // cert verify auth type + bool pending_; + bool resumable_; // new conns by session + uint16 encrypt_size_; // current msg encrypt sz + Cipher suite_[SUITE_LEN]; // choosen suite + uint8 suites_size_; + Cipher suites_[MAX_SUITE_SZ]; + char cipher_name_[MAX_SUITE_NAME]; + char cipher_list_[MAX_CIPHERS][MAX_SUITE_NAME]; + bool removeDH_; // for server's later use + + Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion, bool haveDH); + + void SetSuites(ProtocolVersion pv, bool removeDH = false, + bool removeRSA = false, bool removeDSA = false); + void SetCipherNames(); +private: + Parameters(const Parameters&); // hide copy + Parameters& operator=(const Parameters&); // and assing +}; + + +input_buffer& operator>>(input_buffer&, RecordLayerHeader&); +output_buffer& operator<<(output_buffer&, const RecordLayerHeader&); + +input_buffer& operator>>(input_buffer&, Message&); +output_buffer& operator<<(output_buffer&, const Message&); + +input_buffer& operator>>(input_buffer&, HandShakeBase&); +output_buffer& operator<<(output_buffer&, const HandShakeBase&); + + +// Message Factory definition +// uses the ContentType enumeration for unique id +typedef Factory MessageFactory; +void InitMessageFactory(MessageFactory&); // registers derived classes + +// HandShake Factory definition +// uses the HandShakeType enumeration for unique id +typedef Factory HandShakeFactory; +void InitHandShakeFactory(HandShakeFactory&); // registers derived classes + +// ServerKey Factory definition +// uses KeyExchangeAlgorithm enumeration for unique id +typedef Factory ServerKeyFactory; +void InitServerKeyFactory(ServerKeyFactory&); + +// ClientKey Factory definition +// uses KeyExchangeAlgorithm enumeration for unique id +typedef Factory ClientKeyFactory; +void InitClientKeyFactory(ClientKeyFactory&); + + +// Message Creators +Message* CreateHandShake(); +Message* CreateCipherSpec(); +Message* CreateAlert(); +Message* CreateData(); + + +// HandShake Creators +HandShakeBase* CreateCertificate(); +HandShakeBase* CreateHelloRequest(); +HandShakeBase* CreateClientHello(); +HandShakeBase* CreateServerHello(); +HandShakeBase* CreateServerKeyExchange(); +HandShakeBase* CreateCertificateRequest(); +HandShakeBase* CreateServerHelloDone(); +HandShakeBase* CreateClientKeyExchange(); +HandShakeBase* CreateCertificateVerify(); +HandShakeBase* CreateFinished(); + + +// ServerKey Exchange Creators +ServerKeyBase* CreateRSAServerKEA(); +ServerKeyBase* CreateDHServerKEA(); +ServerKeyBase* CreateFortezzaServerKEA(); + +// ClientKey Exchange Creators +ClientKeyBase* CreateRSAClient(); +ClientKeyBase* CreateDHClient(); +ClientKeyBase* CreateFortezzaClient(); + + + +} // naemspace + +#endif // yaSSL_IMP_HPP diff --git a/mysql/extra/yassl/include/yassl_int.hpp b/mysql/extra/yassl/include/yassl_int.hpp new file mode 100644 index 0000000..240cf94 --- /dev/null +++ b/mysql/extra/yassl/include/yassl_int.hpp @@ -0,0 +1,725 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL internal header defines SSL supporting types not specified in the + * draft along with type conversion functions and openssl compatibility + */ + + +#ifndef yaSSL_INT_HPP +#define yaSSL_INT_HPP + +#include "yassl_imp.hpp" +#include "yassl_error.hpp" +#include "crypto_wrapper.hpp" +#include "cert_wrapper.hpp" +#include "log.hpp" +#include "lock.hpp" +#include "openssl/ssl.h" // ASN1_STRING and DH + +// Check if _POSIX_THREADS should be forced +#if !defined(_POSIX_THREADS) && defined(__hpux) +// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented +#define _POSIX_THREADS +#endif + +#ifdef _POSIX_THREADS + #include +#endif + + +namespace STL = STL_NAMESPACE; + + +namespace yaSSL { + + +// State Machine for Record Layer Protocol +enum RecordLayerState { + recordNotReady = 0, // fatal error, no more processing + recordReady +}; + + +// State Machine for HandShake Protocol +enum HandShakeState { + handShakeNotReady = 0, // fatal error, no more processing + preHandshake, // initial state + inHandshake, // handshake started + handShakeReady // handshake done +}; + + +// client input HandShake state, use if HandShakeState == inHandShake +enum ClientState { + serverNull = 0, + serverHelloComplete, + serverCertComplete, + serverKeyExchangeComplete, + serverHelloDoneComplete, + serverFinishedComplete +}; + + +// server input HandShake state, use if HandShakeState == inHandShake +enum ServerState { + clientNull = 0, + clientHelloComplete, + clientKeyExchangeComplete, + clientFinishedComplete +}; + + +// client connect state for nonblocking restart +enum ConnectState { + CONNECT_BEGIN = 0, + CLIENT_HELLO_SENT, + FIRST_REPLY_DONE, + FINISHED_DONE, + SECOND_REPLY_DONE +}; + + +// server accpet state for nonblocking restart +enum AcceptState { + ACCEPT_BEGIN = 0, + ACCEPT_FIRST_REPLY_DONE, + SERVER_HELLO_DONE, + ACCEPT_SECOND_REPLY_DONE, + ACCEPT_FINISHED_DONE, + ACCEPT_THIRD_REPLY_DONE +}; + + +// track received messages to explicitly disallow duplicate messages +struct RecvdMessages { + uint8 gotClientHello_; + uint8 gotServerHello_; + uint8 gotCert_; + uint8 gotServerKeyExchange_; + uint8 gotCertRequest_; + uint8 gotServerHelloDone_; + uint8 gotCertVerify_; + uint8 gotClientKeyExchange_; + uint8 gotFinished_; + RecvdMessages() : gotClientHello_(0), gotServerHello_(0), gotCert_(0), + gotServerKeyExchange_(0), gotCertRequest_(0), + gotServerHelloDone_(0), gotCertVerify_(0), + gotClientKeyExchange_(0), gotFinished_(0) + {} +}; + + +// combines all states +class States { + RecordLayerState recordLayer_; + HandShakeState handshakeLayer_; + ClientState clientState_; + ServerState serverState_; + ConnectState connectState_; + AcceptState acceptState_; + RecvdMessages recvdMessages_; + char errorString_[MAX_ERROR_SZ]; + YasslError what_; +public: + States(); + + const RecordLayerState& getRecord() const; + const HandShakeState& getHandShake() const; + const ClientState& getClient() const; + const ServerState& getServer() const; + const ConnectState& GetConnect() const; + const AcceptState& GetAccept() const; + const char* getString() const; + YasslError What() const; + + RecordLayerState& useRecord(); + HandShakeState& useHandShake(); + ClientState& useClient(); + ServerState& useServer(); + ConnectState& UseConnect(); + AcceptState& UseAccept(); + char* useString(); + void SetError(YasslError); + int SetMessageRecvd(HandShakeType); +private: + States(const States&); // hide copy + States& operator=(const States&); // and assign +}; + + +// holds all factories +class sslFactory { + MessageFactory messageFactory_; // creates new messages by type + HandShakeFactory handShakeFactory_; // creates new handshake types + ServerKeyFactory serverKeyFactory_; // creates new server key types + ClientKeyFactory clientKeyFactory_; // creates new client key types + + sslFactory(); // only GetSSL_Factory creates +public: + const MessageFactory& getMessage() const; + const HandShakeFactory& getHandShake() const; + const ServerKeyFactory& getServerKey() const; + const ClientKeyFactory& getClientKey() const; + + friend sslFactory& GetSSL_Factory(); // singleton creator +private: + sslFactory(const sslFactory&); // hide copy + sslFactory& operator=(const sslFactory&); // and assign +}; + + +#undef X509_NAME // wincrypt.h clash + +// openSSL X509 names +class X509_NAME { + char* name_; + size_t sz_; + int cnPosition_; // start of common name, -1 is none + int cnLen_; // length of above + ASN1_STRING entry_; +public: + X509_NAME(const char*, size_t sz, int pos, int len); + ~X509_NAME(); + + const char* GetName() const; + ASN1_STRING* GetEntry(int i); + size_t GetLength() const; + int GetCnPosition() const { return cnPosition_; } + int GetCnLength() const { return cnLen_; } + +private: + X509_NAME(const X509_NAME&); // hide copy + X509_NAME& operator=(const X509_NAME&); // and assign +}; + + +class StringHolder { + ASN1_STRING asnString_; +public: + StringHolder(const char* str, int sz, byte type= 0); + ~StringHolder(); + + ASN1_STRING* GetString(); +private: + StringHolder(const StringHolder&); // hide copy + StringHolder& operator=(const StringHolder&); // and assign +}; + + +// openSSL X509 +class X509 { + X509_NAME issuer_; + X509_NAME subject_; + StringHolder beforeDate_; // not valid before + StringHolder afterDate_; // not valid after +public: + X509(const char* i, size_t, const char* s, size_t, + ASN1_STRING *b, ASN1_STRING *a, int, int, int, int); + ~X509() {} + + X509_NAME* GetIssuer(); + X509_NAME* GetSubject(); + + ASN1_STRING* GetBefore(); + ASN1_STRING* GetAfter(); + +private: + X509(const X509&); // hide copy + X509& operator=(const X509&); // and assign +}; + + +// openSSL bignum +struct BIGNUM { + /* + gcc 2.96 fix: because of two Integer classes (yaSSL::Integer and + TaoCrypt::Integer), we need to explicitly state the namespace + here to let gcc 2.96 deduce the correct type. + */ + yaSSL::Integer int_; + void assign(const byte* b, uint s) { int_.assign(b,s); } +}; + + +// openSSL session +class SSL_SESSION { + opaque sessionID_[ID_LEN]; + opaque master_secret_[SECRET_LEN]; + Cipher suite_[SUITE_LEN]; + uint bornOn_; // create time in seconds + uint timeout_; // timeout in seconds + RandomPool& random_; // will clean master secret + X509* peerX509_; +public: + explicit SSL_SESSION(RandomPool&); + SSL_SESSION(const SSL&, RandomPool&); + ~SSL_SESSION(); + + const opaque* GetID() const; + const opaque* GetSecret() const; + const Cipher* GetSuite() const; + uint GetBornOn() const; + uint GetTimeOut() const; + X509* GetPeerX509() const; + void SetTimeOut(uint); + + SSL_SESSION& operator=(const SSL_SESSION&); // allow assign for resumption +private: + SSL_SESSION(const SSL_SESSION&); // hide copy + + void CopyX509(X509*); +}; + + +// holds all sessions +class Sessions { + STL::list list_; + RandomPool random_; // for session cleaning + Mutex mutex_; // no-op for single threaded + int count_; // flush counter + + Sessions() : count_(0) {} // only GetSessions can create +public: + SSL_SESSION* lookup(const opaque*, SSL_SESSION* copy = 0); + void add(const SSL&); + void remove(const opaque*); + void Flush(); + + ~Sessions(); + + friend void Session_initialize(); + friend Sessions& GetSessions(); // singleton creator +private: + Sessions(const Sessions&); // hide copy + Sessions& operator=(const Sessions&); // and assign +}; + + +#ifdef _POSIX_THREADS + typedef pthread_t THREAD_ID_T; +#else + typedef DWORD THREAD_ID_T; +#endif + +// thread error data +struct ThreadError { + THREAD_ID_T threadID_; + int errorID_; +}; + + +// holds all errors +class Errors { + STL::list list_; + Mutex mutex_; + + Errors() {} // only GetErrors can create +public: + int Lookup(bool peek); // self lookup + void Add(int); + void Remove(); // remove self + + ~Errors() {} + + friend Errors& GetErrors(); // singleton creator +private: + Errors(const Errors&); // hide copy + Errors& operator=(const Errors); // and assign +}; + + +Sessions& GetSessions(); // forward singletons +sslFactory& GetSSL_Factory(); +Errors& GetErrors(); + + +// openSSL method and context types +class SSL_METHOD { + ProtocolVersion version_; + ConnectionEnd side_; + bool verifyPeer_; // request or send certificate + bool verifyNone_; // whether to verify certificate + bool failNoCert_; + bool multipleProtocol_; // for SSLv23 compatibility +public: + SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv, + bool multipleProtocol = false); + + ProtocolVersion getVersion() const; + ConnectionEnd getSide() const; + + void setVerifyPeer(); + void setVerifyNone(); + void setFailNoCert(); + + bool verifyPeer() const; + bool verifyNone() const; + bool failNoCert() const; + bool multipleProtocol() const; +private: + SSL_METHOD(const SSL_METHOD&); // hide copy + SSL_METHOD& operator=(const SSL_METHOD&); // and assign +}; + + +struct Ciphers { + bool setSuites_; // user set suites from default + byte suites_[MAX_SUITE_SZ]; // new suites + int suiteSz_; // suite length in bytes + + Ciphers() : setSuites_(false), suiteSz_(0) {} +}; + + +struct DH; // forward + + +// save for SSL construction +struct DH_Parms { + Integer p_; + Integer g_; + bool set_; // if set by user + + DH_Parms() : set_(false) {} +}; + + +enum StatsField { + Accept, Connect, AcceptGood, ConnectGood, AcceptRenegotiate, + ConnectRenegotiate, Hits, CbHits, CacheFull, Misses, Timeouts, Number, + GetCacheSize, VerifyMode, VerifyDepth +}; + + +// SSL stats +struct Stats { + long accept_; + long connect_; + long acceptGood_; + long connectGood_; + long acceptRenegotiate_; + long connectRenegotiate_; + + long hits_; + long cbHits_; + long cacheFull_; + long misses_; + long timeouts_; + long number_; + long getCacheSize_; + + int verifyMode_; + int verifyDepth_; +public: + Stats() : accept_(0), connect_(0), acceptGood_(0), connectGood_(0), + acceptRenegotiate_(0), connectRenegotiate_(0), hits_(0), cbHits_(0), + cacheFull_(0), misses_(0), timeouts_(0), number_(0), getCacheSize_(0), + verifyMode_(0), verifyDepth_(0) + {} +private: + Stats(const Stats&); // hide copy + Stats& operator=(const Stats&); // and assign +}; + + +// the SSL context +class SSL_CTX { +public: + typedef STL::list CertList; +private: + SSL_METHOD* method_; + x509* certificate_; + x509* privateKey_; + CertList caList_; + Ciphers ciphers_; + DH_Parms dhParms_; + pem_password_cb passwordCb_; + void* userData_; + bool sessionCacheOff_; + bool sessionCacheFlushOff_; + Stats stats_; + Mutex mutex_; // for Stats + VerifyCallback verifyCallback_; +public: + explicit SSL_CTX(SSL_METHOD* meth); + ~SSL_CTX(); + + const x509* getCert() const; + const x509* getKey() const; + const SSL_METHOD* getMethod() const; + const Ciphers& GetCiphers() const; + const DH_Parms& GetDH_Parms() const; + const Stats& GetStats() const; + VerifyCallback getVerifyCallback() const; + pem_password_cb GetPasswordCb() const; + void* GetUserData() const; + bool GetSessionCacheOff() const; + bool GetSessionCacheFlushOff() const; + + void setVerifyPeer(); + void setVerifyNone(); + void setFailNoCert(); + void setVerifyCallback(VerifyCallback); + bool SetCipherList(const char*); + bool SetDH(const DH&); + void SetPasswordCb(pem_password_cb cb); + void SetUserData(void*); + void SetSessionCacheOff(); + void SetSessionCacheFlushOff(); + void SetMethod(SSL_METHOD* meth); + void IncrementStats(StatsField); + void AddCA(x509* ca); + const CertList& GetCA_List() const; + + friend int read_file(SSL_CTX*, const char*, int, CertType); +private: + SSL_CTX(const SSL_CTX&); // hide copy + SSL_CTX& operator=(const SSL_CTX&); // and assign +}; + + +// holds all cryptographic types +class Crypto { + Digest* digest_; // agreed upon digest + BulkCipher* cipher_; // agreed upon cipher + DiffieHellman* dh_; // dh parms + RandomPool random_; // random number generator + CertManager cert_; // manages certificates +public: + explicit Crypto(); + ~Crypto(); + + const Digest& get_digest() const; + const BulkCipher& get_cipher() const; + const DiffieHellman& get_dh() const; + const RandomPool& get_random() const; + const CertManager& get_certManager() const; + + Digest& use_digest(); + BulkCipher& use_cipher(); + DiffieHellman& use_dh(); + RandomPool& use_random(); + CertManager& use_certManager(); + + void SetDH(DiffieHellman*); + void SetDH(const DH_Parms&); + void setDigest(Digest*); + void setCipher(BulkCipher*); + + bool DhSet(); +private: + Crypto(const Crypto&); // hide copy + Crypto& operator=(const Crypto&); // and assign +}; + + +// holds all handshake and verify hashes +class sslHashes { + MD5 md5HandShake_; // md5 handshake hash + SHA shaHandShake_; // sha handshake hash + Finished verify_; // peer's verify hash + Hashes certVerify_; // peer's cert verify hash +public: + sslHashes() {} + + const MD5& get_MD5() const; + const SHA& get_SHA() const; + const Finished& get_verify() const; + const Hashes& get_certVerify() const; + + MD5& use_MD5(); + SHA& use_SHA(); + Finished& use_verify(); + Hashes& use_certVerify(); +private: + sslHashes(const sslHashes&); // hide copy + sslHashes& operator=(const sslHashes&); // and assign +}; + + +// holds input and output buffers +class Buffers { +public: + typedef STL::list inputList; + typedef STL::list outputList; + int prevSent; // previous plain text bytes sent when got WANT_WRITE + int plainSz; // plain text bytes in buffer to send when got WANT_WRITE +private: + inputList dataList_; // list of users app data / handshake + outputList handShakeList_; // buffered handshake msgs + input_buffer* rawInput_; // buffered raw input yet to process + output_buffer* output_; // WANT_WRITE buffered output +public: + Buffers(); + ~Buffers(); + + const inputList& getData() const; + const outputList& getHandShake() const; + + inputList& useData(); + outputList& useHandShake(); + + void SetRawInput(input_buffer*); // takes ownership + input_buffer* TakeRawInput(); // takes ownership + void SetOutput(output_buffer*); // takes ownership + output_buffer* TakeOutput(); // takes ownership +private: + Buffers(const Buffers&); // hide copy + Buffers& operator=(const Buffers&); // and assign +}; + + +// wraps security parameters +class Security { + Connection conn_; // connection information + Parameters parms_; // may be pending + SSL_SESSION resumeSession_; // if resuming + SSL_CTX* ctx_; // context used to init + bool resuming_; // trying to resume +public: + Security(ProtocolVersion, RandomPool&, ConnectionEnd, const Ciphers&, + SSL_CTX*, bool); + + const SSL_CTX* GetContext() const; + const Connection& get_connection() const; + const Parameters& get_parms() const; + const SSL_SESSION& get_resume() const; + bool get_resuming() const; + + Connection& use_connection(); + Parameters& use_parms(); + SSL_SESSION& use_resume(); + + void set_resuming(bool b); +private: + Security(const Security&); // hide copy + Security& operator=(const Security&); // and assign +}; + + +// THE SSL type +class SSL { + Crypto crypto_; // agreed crypto agents + Security secure_; // Connection and Session parms + States states_; // Record and HandShake states + sslHashes hashes_; // handshake, finished hashes + Socket socket_; // socket wrapper + Buffers buffers_; // buffered handshakes and data + Log log_; // logger + bool quietShutdown_; + + // optimization variables + bool has_data_; // buffered data ready? +public: + SSL(SSL_CTX* ctx); + + // gets and uses + const Crypto& getCrypto() const; + const Security& getSecurity() const; + const States& getStates() const; + const sslHashes& getHashes() const; + const sslFactory& getFactory() const; + const Socket& getSocket() const; + YasslError GetError() const; + bool GetMultiProtocol() const; + bool CompressionOn() const; + + Crypto& useCrypto(); + Security& useSecurity(); + States& useStates(); + sslHashes& useHashes(); + Socket& useSocket(); + Log& useLog(); + Buffers& useBuffers(); + + bool HasData() const; + bool GetQuietShutdown() const; + + // sets + void set_pending(Cipher suite); + void set_random(const opaque*, ConnectionEnd); + void set_sessionID(const opaque*); + void set_session(SSL_SESSION*); + void set_preMaster(const opaque*, uint); + void set_masterSecret(const opaque*); + void SetError(YasslError); + int SetCompression(); + void UnSetCompression(); + void SetQuietShutdown(bool mode); + + // helpers + bool isTLS() const; + bool isTLSv1_1() const; + void order_error(); + void makeMasterSecret(); + void makeTLSMasterSecret(); + void addData(input_buffer* data); + void fillData(Data&); + void PeekData(Data&); + void addBuffer(output_buffer* b); + void flushBuffer(); + void verifyState(const RecordLayerHeader&); + void verifyState(const HandShakeHeader&); + void verifyState(ClientState); + void verifyState(ServerState); + void verfiyHandShakeComplete(); + void matchSuite(const opaque*, uint length); + void deriveKeys(); + void deriveTLSKeys(); + void Send(const byte*, uint); + void SendWriteBuffered(); + + uint bufferedData(); + uint get_SEQIncrement(bool); + + const byte* get_macSecret(bool); +private: + void storeKeys(const opaque*); + void setKeys(); + void verifyClientState(HandShakeType); + void verifyServerState(HandShakeType); + + SSL(const SSL&); // hide copy + const SSL& operator=(const SSL&); // and assign +}; + + +// compression +int Compress(const byte*, int, input_buffer&); +int DeCompress(input_buffer&, int, input_buffer&); + + +// conversion functions +void c32to24(uint32, uint24&); +void c24to32(const uint24, uint32&); + +uint32 c24to32(const uint24); + +void ato16(const opaque*, uint16&); +void ato24(const opaque*, uint24&); + +void c16toa(uint16, opaque*); +void c24toa(const uint24, opaque*); +void c32toa(uint32 u32, opaque*); + + +} // naemspace + +#endif // yaSSL_INT_HPP diff --git a/mysql/extra/yassl/include/yassl_types.hpp b/mysql/extra/yassl/include/yassl_types.hpp new file mode 100644 index 0000000..129661c --- /dev/null +++ b/mysql/extra/yassl/include/yassl_types.hpp @@ -0,0 +1,540 @@ +/* + Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* yaSSL types header defines all constants, enums, and typedefs + * from the SSL.v3 specification "draft-freier-ssl-version3-02.txt" + */ + + +#ifndef yaSSL_TYPES_HPP +#define yaSSL_TYPES_HPP + +#include +#include "type_traits.hpp" + + +#ifdef _MSC_VER + // disable conversion warning + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable:4244 4996) +#endif + + +#ifdef _MSC_VER + // disable conversion warning + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable:4244 4996) +#endif + + +namespace yaSSL { + +#define YASSL_LIB + + +#ifdef YASSL_PURE_C + + // library allocation + struct new_t {}; // yaSSL New type + extern new_t ys; // pass in parameter + + } // namespace yaSSL + + void* operator new (size_t, yaSSL::new_t); + void* operator new[](size_t, yaSSL::new_t); + + void operator delete (void*, yaSSL::new_t); + void operator delete[](void*, yaSSL::new_t); + + + namespace yaSSL { + + + template + void ysDelete(T* ptr) + { + if (ptr) ptr->~T(); + ::operator delete(ptr, yaSSL::ys); + } + + template + void ysArrayDelete(T* ptr) + { + // can't do array placement destruction since not tracking size in + // allocation, only allow builtins to use array placement since they + // don't need destructors called + typedef char builtin[TaoCrypt::IsFundamentalType::Yes ? 1 : -1]; + (void)sizeof(builtin); + + ::operator delete[](ptr, yaSSL::ys); + } + + #define NEW_YS new (yaSSL::ys) + + // to resolve compiler generated operator delete on base classes with + // virtual destructors (when on stack) + class virtual_base { + public: + static void operator delete(void*) { } + }; + + +#else // YASSL_PURE_C + + + template + void ysDelete(T* ptr) + { + delete ptr; + } + + template + void ysArrayDelete(T* ptr) + { + delete[] ptr; + } + + #define NEW_YS new + + class virtual_base {}; + + + +#endif // YASSL_PURE_C + + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef uint8 uint24[3]; +typedef uint32 uint64[2]; + +typedef uint8 opaque; +typedef opaque byte; + +typedef unsigned int uint; + + +#ifdef USE_SYS_STL + // use system STL + #define STL_VECTOR_FILE + #define STL_LIST_FILE + #define STL_ALGORITHM_FILE + #define STL_MEMORY_FILE + #define STL_PAIR_FILE + + #define STL_NAMESPACE std +#else + // use mySTL + #define STL_VECTOR_FILE "vector.hpp" + #define STL_LIST_FILE "list.hpp" + #define STL_ALGORITHM_FILE "algorithm.hpp" + #define STL_MEMORY_FILE "memory.hpp" + #define STL_PAIR_FILE "pair.hpp" + + #define STL_NAMESPACE mySTL +#endif + + +#ifdef min + #undef min +#endif + +template +T min(T a, T b) +{ + return a < b ? a : b; +} + + + +// all length constants in bytes +const int ID_LEN = 32; // session id length +const int SUITE_LEN = 2; // cipher suite length +const int SECRET_LEN = 48; // pre RSA and all master secret length +const int MASTER_ROUNDS = 3; // master secret derivation rounds +const int RAN_LEN = 32; // client and server random length +const int MAC_BLOCK_SZ = 64; // MAC block size, & padding +const int MD5_LEN = 16; // MD5 digest length +const int SHA_LEN = 20; // SHA digest length +const int RMD_LEN = 20; // RIPEMD-160 digest length +const int PREFIX = 3; // up to 3 prefix letters for secret rounds +const int KEY_PREFIX = 7; // up to 7 prefix letters for key rounds +const int FORTEZZA_MAX = 128; // Maximum Fortezza Key length +const int MAX_SUITE_SZ = 128; // 64 max suites * sizeof(suite) +const int MAX_SUITE_NAME = 48; // max length of suite name +const int MAX_CIPHERS = 32; // max supported ciphers for cipher list +const int SIZEOF_ENUM = 1; // SSL considers an enum 1 byte, not 4 +const int SIZEOF_SENDER = 4; // Sender constant, for finished generation +const int PAD_MD5 = 48; // pad length 1 and 2 for md5 finished +const int PAD_SHA = 40; // should be 44, specd wrong by netscape +const int PAD_RMD = 44; // pad length for RIPEMD-160, some use 40?? +const int CERT_HEADER = 3; // always use 3 bytes for certificate +const int CERT_TYPES = 7; // certificate request types +const int REQUEST_HEADER = 2; // request uses 2 bytes +const int VERIFY_HEADER = 2; // verify length field +const int MIN_CERT_TYPES = 1; // minimum certificate request types +const int MIN_DIS_NAMES = 3; // minimum distinguished names +const int MIN_DIS_SIZE = 1; // minimum distinguished name size +const int RECORD_HEADER = 5; // type + version + length(2) +const int HANDSHAKE_HEADER = 4; // type + length(3) +const int FINISHED_SZ = MD5_LEN + SHA_LEN; // sizeof finished data +const int TLS_FINISHED_SZ = 12; // TLS verify data size +const int SEQ_SZ = 8; // 64 bit sequence number +const int LENGTH_SZ = 2; // length field for HMAC, data only +const int VERSION_SZ = SIZEOF_ENUM * 2; // SSL/TLS length of version +const int DES_KEY_SZ = 8; // DES Key length +const int DES_EDE_KEY_SZ = 24; // DES EDE Key length +const int DES_BLOCK = 8; // DES is always fixed block size 8 +const int DES_IV_SZ = DES_BLOCK; // Init Vector length for DES +const int RC4_KEY_SZ = 16; // RC4 Key length +const int AES_128_KEY_SZ = 16; // AES 128bit Key length +const int AES_192_KEY_SZ = 24; // AES 192bit Key length +const int AES_256_KEY_SZ = 32; // AES 256bit Key length +const int AES_BLOCK_SZ = 16; // AES 128bit block size, rfc 3268 +const int AES_IV_SZ = AES_BLOCK_SZ; // AES Init Vector length +const int DSS_SIG_SZ = 40; // two 20 byte high byte first Integers +const int DSS_ENCODED_EXTRA = 6; // seqID + len(1) + (intID + len(1)) * 2 +const int EVP_SALT_SZ = 8; +const int MASTER_LABEL_SZ = 13; // TLS master secret label size +const int KEY_LABEL_SZ = 13; // TLS key block expansion size +const int FINISHED_LABEL_SZ = 15; // TLS finished lable length +const int SEED_LEN = RAN_LEN * 2; // TLS seed, client + server random +const int DEFAULT_TIMEOUT = 500; // Default Session timeout in seconds +const int MAX_RECORD_SIZE = 16384; // 2^14, max size by standard +const int COMPRESS_EXTRA = 1024; // extra compression possible addition +const int SESSION_FLUSH_COUNT = 256; // when to flush session cache +const int MAX_PAD_SIZE = 256; // max TLS padding size +const int COMPRESS_CONSTANT = 13; // compression calculation constant +const int COMPRESS_UPPER = 55; // compression calculation numerator +const int COMPRESS_LOWER = 64; // compression calculation denominator +const int COMPRESS_DUMMY_SIZE = 64; // compression dummy round size + +typedef uint8 Cipher; // first byte is always 0x00 for SSLv3 & TLS + +typedef opaque Random[RAN_LEN]; + +typedef opaque* DistinguishedName; + +typedef bool IsExportable; + + +enum CompressionMethod { no_compression = 0, zlib = 221 }; + +enum CipherType { stream, block }; + +enum CipherChoice { change_cipher_spec_choice = 1 }; + +enum PublicValueEncoding { implicit_encoding, explicit_encoding }; + +enum ConnectionEnd { server_end, client_end }; + +enum AlertLevel { warning = 1, fatal = 2 }; + + + +// Record Layer Header identifier from page 12 +enum ContentType { + no_type = 0, + change_cipher_spec = 20, + alert = 21, + handshake = 22, + application_data = 23 +}; + + +// HandShake Layer Header identifier from page 20 +enum HandShakeType { + no_shake = -1, + hello_request = 0, + client_hello = 1, + server_hello = 2, + certificate = 11, + server_key_exchange = 12, + certificate_request = 13, + server_hello_done = 14, + certificate_verify = 15, + client_key_exchange = 16, + finished = 20 +}; + + +// Valid Alert types from page 16/17 +enum AlertDescription { + close_notify = 0, + unexpected_message = 10, + bad_record_mac = 20, + decompression_failure = 30, + handshake_failure = 40, + no_certificate = 41, + bad_certificate = 42, + unsupported_certificate = 43, + certificate_revoked = 44, + certificate_expired = 45, + certificate_unknown = 46, + illegal_parameter = 47 +}; + + +// Supported Key Exchange Protocols +enum KeyExchangeAlgorithm { + no_kea = 0, + rsa_kea, + diffie_hellman_kea, + fortezza_kea +}; + + +// Supported Authentication Schemes +enum SignatureAlgorithm { + anonymous_sa_algo = 0, + rsa_sa_algo, + dsa_sa_algo +}; + + +// Valid client certificate request types from page 27 +enum ClientCertificateType { + rsa_sign = 1, + dss_sign = 2, + rsa_fixed_dh = 3, + dss_fixed_dh = 4, + rsa_ephemeral_dh = 5, + dss_ephemeral_dh = 6, + fortezza_kea_cert = 20 +}; + + +// Supported Ciphers from page 43 +enum BulkCipherAlgorithm { + cipher_null, + rc4, + rc2, + des, + triple_des, // leading 3 (3des) not valid identifier + des40, + idea, + aes +}; + + +// Supported Message Authentication Codes from page 43 +enum MACAlgorithm { + no_mac, + md5, + sha, + rmd +}; + + +// Certificate file Type +enum CertType { Cert = 0, PrivateKey, CA }; + + +// all Cipher Suites from pages 41/42 +const Cipher SSL_NULL_WITH_NULL_NULL = 0; // { 0x00, 0x00 } +const Cipher SSL_RSA_WITH_NULL_MD5 = 1; // { 0x00, 0x01 } +const Cipher SSL_RSA_WITH_NULL_SHA = 2; // { 0x00, 0x02 } +const Cipher SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3; // { 0x00, 0x03 } +const Cipher SSL_RSA_WITH_RC4_128_MD5 = 4; // { 0x00, 0x04 } +const Cipher SSL_RSA_WITH_RC4_128_SHA = 5; // { 0x00, 0x05 } +const Cipher SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6; // { 0x00, 0x06 } +const Cipher SSL_RSA_WITH_IDEA_CBC_SHA = 7; // { 0x00, 0x07 } +const Cipher SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8; // { 0x00, 0x08 } +const Cipher SSL_RSA_WITH_DES_CBC_SHA = 9; // { 0x00, 0x09 } +const Cipher SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10; // { 0x00, 0x0A } +const Cipher SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11; // { 0x00, 0x0B } +const Cipher SSL_DH_DSS_WITH_DES_CBC_SHA = 12; // { 0x00, 0x0C } +const Cipher SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13; // { 0x00, 0x0D } +const Cipher SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14; // { 0x00, 0x0E } +const Cipher SSL_DH_RSA_WITH_DES_CBC_SHA = 15; // { 0x00, 0x0F } +const Cipher SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16; // { 0x00, 0x10 } +const Cipher SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17; // { 0x00, 0x11 } +const Cipher SSL_DHE_DSS_WITH_DES_CBC_SHA = 18; // { 0x00, 0x12 } +const Cipher SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19; // { 0x00, 0x13 } +const Cipher SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20; // { 0x00, 0x14 } +const Cipher SSL_DHE_RSA_WITH_DES_CBC_SHA = 21; // { 0x00, 0x15 } +const Cipher SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22; // { 0x00, 0x16 } +const Cipher SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23; // { 0x00, 0x17 } +const Cipher SSL_DH_anon_WITH_RC4_128_MD5 = 24; // { 0x00, 0x18 } +const Cipher SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25; // { 0x00, 0x19 } +const Cipher SSL_DH_anon_WITH_DES_CBC_SHA = 26; // { 0x00, 0x1A } +const Cipher SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27; // { 0x00, 0x1B } +const Cipher SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28; // { 0x00, 0x1C } +const Cipher SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29; // { 0x00, 0x1D } +const Cipher SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30; // { 0x00, 0x1E } + +// .. to 0x2B uses Kerberos Authentication + + +// TLS AES extensions +const Cipher TLS_RSA_WITH_AES_128_CBC_SHA = 47; // { 0x00, 0x2F } +const Cipher TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48; // { 0x00, 0x30 } +const Cipher TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49; // { 0x00, 0x31 } +const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50; // { 0x00, 0x32 } +const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51; // { 0x00, 0x33 } +const Cipher TLS_DH_anon_WITH_AES_128_CBC_SHA = 52; // { 0x00, 0x34 } + +const Cipher TLS_RSA_WITH_AES_256_CBC_SHA = 53; // { 0x00, 0x35 } +const Cipher TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54; // { 0x00, 0x36 } +const Cipher TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55; // { 0x00, 0x37 } +const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56; // { 0x00, 0x38 } +const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57; // { 0x00, 0x39 } +const Cipher TLS_DH_anon_WITH_AES_256_CBC_SHA = 58; // { 0x00, 0x3A } + + +// OpenPGP extensions + +const Cipher TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114; // { 0x00, 0x72 }; +const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115; // { 0x00, 0x73 }; +const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116; // { 0x00, 0x74 }; +const Cipher TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119; // { 0x00, 0x77 }; +const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120; // { 0x00, 0x78 }; +const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121; // { 0x00, 0x79 }; +const Cipher TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124; // { 0x00, 0x7C }; +const Cipher TLS_RSA_WITH_AES_128_CBC_RMD160 = 125; // { 0x00, 0x7D }; +const Cipher TLS_RSA_WITH_AES_256_CBC_RMD160 = 126; // { 0x00, 0x7E }; + + +const char* const null_str = ""; + +const char* const cipher_names[128] = +{ + null_str, // SSL_NULL_WITH_NULL_NULL = 0 + null_str, // SSL_RSA_WITH_NULL_MD5 = 1 + null_str, // SSL_RSA_WITH_NULL_SHA = 2 + null_str, // SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3 + "RC4-MD5", // SSL_RSA_WITH_RC4_128_MD5 = 4 + "RC4-SHA", // SSL_RSA_WITH_RC4_128_SHA = 5 + null_str, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6 + null_str, // SSL_RSA_WITH_IDEA_CBC_SHA = 7 + null_str, // SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8 + "DES-CBC-SHA", // SSL_RSA_WITH_DES_CBC_SHA = 9 + "DES-CBC3-SHA", // SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10 + + null_str, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11 + null_str, // SSL_DH_DSS_WITH_DES_CBC_SHA = 12 + null_str, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13 + null_str, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14 + null_str, // SSL_DH_RSA_WITH_DES_CBC_SHA = 15 + null_str, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16 + null_str, // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17 + "EDH-DSS-DES-CBC-SHA", // SSL_DHE_DSS_WITH_DES_CBC_SHA = 18 + "EDH-DSS-DES-CBC3-SHA", // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19 + null_str, // SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20 + + "EDH-RSA-DES-CBC-SHA", // SSL_DHE_RSA_WITH_DES_CBC_SHA = 21 + "EDH-RSA-DES-CBC3-SHA", // SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22 + null_str, // SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23 + null_str, // SSL_DH_anon_WITH_RC4_128_MD5 = 24 + null_str, // SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25 + null_str, // SSL_DH_anon_WITH_DES_CBC_SHA = 26 + null_str, // SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27 + null_str, // SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28 + null_str, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29 + null_str, // SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30 + + null_str, null_str, null_str, null_str, null_str, // 31 - 35 + null_str, null_str, null_str, null_str, null_str, // 36 - 40 + null_str, null_str, null_str, null_str, null_str, // 41 - 45 + null_str, // 46 + + // TLS AES extensions + "AES128-SHA", // TLS_RSA_WITH_AES_128_CBC_SHA = 47 + null_str, // TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48 + null_str, // TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49 + "DHE-DSS-AES128-SHA", // TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50 + "DHE-RSA-AES128-SHA", // TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51 + null_str, // TLS_DH_anon_WITH_AES_128_CBC_SHA = 52 + + "AES256-SHA", // TLS_RSA_WITH_AES_256_CBC_SHA = 53 + null_str, // TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54 + null_str, // TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55 + "DHE-DSS-AES256-SHA", // TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56 + "DHE-RSA-AES256-SHA", // TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57 + null_str, // TLS_DH_anon_WITH_AES_256_CBC_SHA = 58 + + null_str, // 59 + null_str, // 60 + null_str, null_str, null_str, null_str, null_str, // 61 - 65 + null_str, null_str, null_str, null_str, null_str, // 66 - 70 + null_str, null_str, null_str, null_str, null_str, // 71 - 75 + null_str, null_str, null_str, null_str, null_str, // 76 - 80 + null_str, null_str, null_str, null_str, null_str, // 81 - 85 + null_str, null_str, null_str, null_str, null_str, // 86 - 90 + null_str, null_str, null_str, null_str, null_str, // 91 - 95 + null_str, null_str, null_str, null_str, null_str, // 96 - 100 + null_str, null_str, null_str, null_str, null_str, // 101 - 105 + null_str, null_str, null_str, null_str, null_str, // 106 - 110 + null_str, null_str, null_str, // 111 - 113 + + "DHE-DSS-DES-CBC3-RMD", // TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114 + "DHE-DSS-AES128-RMD", // TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115 + "DHE-DSS-AES256-RMD", // TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116 + null_str, // 117 + null_str, // 118 + "DHE-RSA-DES-CBC3-RMD", // TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119 + "DHE-RSA-AES128-RMD", // TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120 + "DHE-RSA-AES256-RMD", // TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121 + null_str, // 122 + null_str, // 123 + "DES-CBC3-RMD", // TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124 + "AES128-RMD", // TLS_RSA_WITH_AES_128_CBC_RMD160 = 125 + "AES256-RMD", // TLS_RSA_WITH_AES_256_CBC_RMD160 = 126 + null_str // 127 +}; + +// fill with MD5 pad size since biggest required +const opaque PAD1[PAD_MD5] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 + }; +const opaque PAD2[PAD_MD5] = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c + }; + +const opaque client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 }; +const opaque server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 }; + +const opaque tls_client[FINISHED_LABEL_SZ + 1] = "client finished"; +const opaque tls_server[FINISHED_LABEL_SZ + 1] = "server finished"; + +const opaque master_label[MASTER_LABEL_SZ + 1] = "master secret"; +const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion"; + + +} // naemspace + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 +/* + gcc 2.96 bails out because of two declarations of byte: yaSSL::byte and + TaoCrypt::byte. TODO: define global types.hpp and move the declaration of + 'byte' there. +*/ +using yaSSL::byte; +#endif + + +#endif // yaSSL_TYPES_HPP diff --git a/mysql/extra/yassl/src/buffer.cpp b/mysql/extra/yassl/src/buffer.cpp new file mode 100644 index 0000000..954fdb5 --- /dev/null +++ b/mysql/extra/yassl/src/buffer.cpp @@ -0,0 +1,330 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL buffer header implements input/output buffers to simulate streaming + * with SSL types and sockets + */ + + +// First include (the generated) my_config.h, to get correct platform defines. +#include "my_config.h" +#include // memcpy +#include "runtime.hpp" +#include "buffer.hpp" +#include "yassl_types.hpp" + +namespace yaSSL { + + + + +/* return 0 on check success, always true for NoCheck policy */ +int NoCheck::check(uint, uint) +{ + return 0; +} + +/* return 0 on check success */ +int Check::check(uint i, uint max) +{ + if (i < max) + return 0; + + return -1; +} + + +/* input_buffer operates like a smart c style array with a checking option, + * meant to be read from through [] with AUTO index or read(). + * Should only write to at/near construction with assign() or raw (e.g., recv) + * followed by add_size with the number of elements added by raw write. + * + * Not using vector because need checked []access, offset, and the ability to + * write to the buffer bulk wise and have the correct size + */ + + +input_buffer::input_buffer() + : size_(0), current_(0), buffer_(0), end_(0), error_(0), zero_(0) +{} + + +input_buffer::input_buffer(uint s) + : size_(0), current_(0), buffer_(NEW_YS byte[s]), end_(buffer_ + s), + error_(0), zero_(0) +{} + + +// with assign +input_buffer::input_buffer(uint s, const byte* t, uint len) + : size_(0), current_(0), buffer_(NEW_YS byte[s]), end_(buffer_ + s), + error_(0), zero_(0) +{ + assign(t, len); +} + + +input_buffer::~input_buffer() +{ + ysArrayDelete(buffer_); +} + + +// users can pass defualt zero length buffer and then allocate +void input_buffer::allocate(uint s) +{ + if (error_ == 0) { + buffer_ = NEW_YS byte[s]; + end_ = buffer_ + s; + } +} + + +// for passing to raw writing functions at beginning, then use add_size +byte* input_buffer::get_buffer() const +{ + return buffer_; +} + + +// after a raw write user can set NEW_YS size +// if you know the size before the write use assign() +void input_buffer::add_size(uint i) +{ + if (error_ == 0 && check(size_ + i-1, get_capacity()) == 0) + size_ += i; + else + error_ = -1; +} + + +uint input_buffer::get_capacity() const +{ + if (error_ == 0) + return end_ - buffer_; + + return 0; +} + + +uint input_buffer::get_current() const +{ + if (error_ == 0) + return current_; + + return 0; +} + + +uint input_buffer::get_size() const +{ + if (error_ == 0) + return size_; + + return 0; +} + + +uint input_buffer::get_remaining() const +{ + if (error_ == 0) + return size_ - current_; + + return 0; +} + + +int input_buffer::get_error() const +{ + return error_; +} + + +void input_buffer::set_error() +{ + error_ = -1; +} + + +void input_buffer::set_current(uint i) +{ + if (error_ == 0 && check(i ? i - 1 : 0, size_) == 0) + current_ = i; + else + error_ = -1; +} + + +// read only access through [], advance current +// user passes in AUTO index for ease of use +const byte& input_buffer::operator[](uint i) +{ + if (error_ == 0 && check(current_, size_) == 0) + return buffer_[current_++]; + + error_ = -1; + return zero_; +} + + +// end of input test +bool input_buffer::eof() +{ + if (error_ != 0) + return true; + + return current_ >= size_; +} + + +// peek ahead +byte input_buffer::peek() +{ + if (error_ == 0 && check(current_, size_) == 0) + return buffer_[current_]; + + error_ = -1; + return 0; +} + + +// write function, should use at/near construction +void input_buffer::assign(const byte* t, uint s) +{ + if (t && error_ == 0 && check(current_, get_capacity()) == 0) { + add_size(s); + if (error_ == 0) { + memcpy(&buffer_[current_], t, s); + return; // success + } + } + + error_ = -1; +} + + +// use read to query input, adjusts current +void input_buffer::read(byte* dst, uint length) +{ + if (dst && error_ == 0 && check(current_ + length - 1, size_) == 0) { + memcpy(dst, &buffer_[current_], length); + current_ += length; + } else { + error_ = -1; + } +} + + + +/* output_buffer operates like a smart c style array with a checking option. + * Meant to be written to through [] with AUTO index or write(). + * Size (current) counter increases when written to. Can be constructed with + * zero length buffer but be sure to allocate before first use. + * Don't use add write for a couple bytes, use [] instead, way less overhead. + * + * Not using vector because need checked []access and the ability to + * write to the buffer bulk wise and retain correct size + */ + + +output_buffer::output_buffer() + : current_(0), buffer_(0), end_(0) +{} + + +// with allocate +output_buffer::output_buffer(uint s) + : current_(0), buffer_(NEW_YS byte[s]), end_(buffer_ + s) +{} + + +// with assign +output_buffer::output_buffer(uint s, const byte* t, uint len) + : current_(0), buffer_(NEW_YS byte[s]), end_(buffer_+ s) +{ + write(t, len); +} + + +output_buffer::~output_buffer() +{ + ysArrayDelete(buffer_); +} + + +uint output_buffer::get_size() const +{ + return current_; +} + + +uint output_buffer::get_capacity() const +{ + return (uint) (end_ - buffer_); +} + + +void output_buffer::set_current(uint c) +{ + check(c, get_capacity()); + current_ = c; +} + + +// users can pass defualt zero length buffer and then allocate +void output_buffer::allocate(uint s) +{ + buffer_ = NEW_YS byte[s]; end_ = buffer_ + s; +} + + +// for passing to reading functions when finished +const byte* output_buffer::get_buffer() const +{ + return buffer_; +} + + +// allow write access through [], update current +// user passes in AUTO as index for ease of use +byte& output_buffer::operator[](uint i) +{ + check(current_, get_capacity()); + return buffer_[current_++]; +} + + +// end of output test +bool output_buffer::eof() +{ + return current_ >= get_capacity(); +} + + +void output_buffer::write(const byte* t, uint s) +{ + check(current_ + s - 1, get_capacity()); + memcpy(&buffer_[current_], t, s); + current_ += s; +} + + + +} // naemspace + diff --git a/mysql/extra/yassl/src/cert_wrapper.cpp b/mysql/extra/yassl/src/cert_wrapper.cpp new file mode 100644 index 0000000..1092e42 --- /dev/null +++ b/mysql/extra/yassl/src/cert_wrapper.cpp @@ -0,0 +1,408 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* The certificate wrapper source implements certificate management functions + * + */ + +#include "runtime.hpp" +#include "cert_wrapper.hpp" +#include "yassl_int.hpp" +#include "error.hpp" + +#if defined(USE_CML_LIB) + #include "cmapi_cpp.h" +#else + #include "asn.hpp" + #include "file.hpp" +#endif // USE_CML_LIB + + +namespace yaSSL { + + +x509::x509(uint sz) : length_(sz), buffer_(NEW_YS opaque[sz]) +{ +} + + +x509::~x509() +{ + ysArrayDelete(buffer_); +} + + +x509::x509(const x509& that) : length_(that.length_), + buffer_(NEW_YS opaque[length_]) +{ + memcpy(buffer_, that.buffer_, length_); +} + + +void x509::Swap(x509& that) +{ + STL::swap(length_, that.length_); + STL::swap(buffer_, that.buffer_); +} + + +x509& x509::operator=(const x509& that) +{ + x509 temp(that); + Swap(temp); + return *this; +} + + +uint x509::get_length() const +{ + return length_; +} + + +const opaque* x509::get_buffer() const +{ + return buffer_; +} + + +opaque* x509::use_buffer() +{ + return buffer_; +} + + +//CertManager +CertManager::CertManager() + : peerX509_(0), selfX509_(0), verifyPeer_(false), verifyNone_(false), failNoCert_(false), + sendVerify_(false), sendBlankCert_(false), verifyCallback_(0) +{} + + +CertManager::~CertManager() +{ + ysDelete(peerX509_); + ysDelete(selfX509_); + + STL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ; + + STL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ; + + STL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ; +} + + +bool CertManager::verifyPeer() const +{ + return verifyPeer_; +} + + +bool CertManager::verifyNone() const +{ + return verifyNone_; +} + + +bool CertManager::failNoCert() const +{ + return failNoCert_; +} + + +bool CertManager::sendVerify() const +{ + return sendVerify_; +} + + +void CertManager::setVerifyPeer() +{ + verifyPeer_ = true; +} + + +void CertManager::setVerifyNone() +{ + verifyNone_ = true; +} + +bool CertManager::sendBlankCert() const +{ + return sendBlankCert_; +} + + +void CertManager::setFailNoCert() +{ + failNoCert_ = true; +} + + +void CertManager::setSendVerify() +{ + sendVerify_ = true; +} + +void CertManager::setSendBlankCert() +{ + sendBlankCert_ = true; +} + + +void CertManager::setVerifyCallback(VerifyCallback vc) +{ + verifyCallback_ = vc; +} + + +void CertManager::AddPeerCert(x509* x) +{ + peerList_.push_back(x); // take ownership +} + + +void CertManager::CopySelfCert(const x509* x) +{ + if (x) + list_.push_back(NEW_YS x509(*x)); +} + + +// add to signers +int CertManager::CopyCaCert(const x509* x) +{ + TaoCrypt::Source source(x->get_buffer(), x->get_length()); + TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_, + TaoCrypt::CertDecoder::CA); + + if (!cert.GetError().What()) { + const TaoCrypt::PublicKey& key = cert.GetPublicKey(); + signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), + cert.GetCommonName(), cert.GetHash())); + } + // just don't add, not an error return cert.GetError().What(); + return 0; +} + + +const x509* CertManager::get_cert() const +{ + return list_.front(); +} + + +const opaque* CertManager::get_peerKey() const +{ + return peerPublicKey_.get_buffer(); +} + + +X509* CertManager::get_peerX509() const +{ + return peerX509_; +} + + +X509* CertManager::get_selfX509() const +{ + return selfX509_; +} + + +SignatureAlgorithm CertManager::get_peerKeyType() const +{ + return peerKeyType_; +} + + +SignatureAlgorithm CertManager::get_keyType() const +{ + return keyType_; +} + + +uint CertManager::get_peerKeyLength() const +{ + return peerPublicKey_.get_size(); +} + + +const opaque* CertManager::get_privateKey() const +{ + return privateKey_.get_buffer(); +} + + +uint CertManager::get_privateKeyLength() const +{ + return privateKey_.get_size(); +} + + +// Validate the peer's certificate list, from root to peer (last to first) +int CertManager::Validate() +{ + CertList::reverse_iterator last = peerList_.rbegin(); + size_t count = peerList_.size(); + + while ( count > 1 ) { + TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); + TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); + + if (int err = cert.GetError().What()) + return err; + + const TaoCrypt::PublicKey& key = cert.GetPublicKey(); + signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), + cert.GetCommonName(), cert.GetHash())); + ++last; + --count; + } + + if (count) { + // peer's is at the front + TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); + TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); + + int err = cert.GetError().What(); + if ( err && err != TaoCrypt::SIG_OTHER_E) + return err; + + uint sz = cert.GetPublicKey().size(); + peerPublicKey_.allocate(sz); + peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz); + + if (cert.GetKeyType() == TaoCrypt::RSAk) + peerKeyType_ = rsa_sa_algo; + else + peerKeyType_ = dsa_sa_algo; + + size_t iSz = strlen(cert.GetIssuer()) + 1; + size_t sSz = strlen(cert.GetCommonName()) + 1; + ASN1_STRING beforeDate, afterDate; + beforeDate.data= (unsigned char *) cert.GetBeforeDate(); + beforeDate.type= cert.GetBeforeDateType(); + beforeDate.length= strlen((char *) beforeDate.data) + 1; + afterDate.data= (unsigned char *) cert.GetAfterDate(); + afterDate.type= cert.GetAfterDateType(); + afterDate.length= strlen((char *) afterDate.data) + 1; + peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), + sSz, &beforeDate, &afterDate, + cert.GetIssuerCnStart(), cert.GetIssuerCnLength(), + cert.GetSubjectCnStart(), cert.GetSubjectCnLength() + ); + + if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) { + X509_STORE_CTX store; + store.error = err; + store.error_depth = static_cast(count) - 1; + store.current_cert = peerX509_; + + int ok = verifyCallback_(0, &store); + if (ok) return 0; + } + + if (err == TaoCrypt::SIG_OTHER_E) return err; + } + return 0; +} + + +// Set the private key +int CertManager::SetPrivateKey(const x509& key) +{ + privateKey_.allocate(key.get_length()); + privateKey_.assign(key.get_buffer(), key.get_length()); + + // set key type + if (x509* cert = list_.front()) { + TaoCrypt::Source source(cert->get_buffer(), cert->get_length()); + TaoCrypt::CertDecoder cd(source, false); + cd.DecodeToKey(); + if (int err = cd.GetError().What()) + return err; + if (cd.GetKeyType() == TaoCrypt::RSAk) + keyType_ = rsa_sa_algo; + else + keyType_ = dsa_sa_algo; + + size_t iSz = strlen(cd.GetIssuer()) + 1; + size_t sSz = strlen(cd.GetCommonName()) + 1; + ASN1_STRING beforeDate, afterDate; + beforeDate.data= (unsigned char *) cd.GetBeforeDate(); + beforeDate.type= cd.GetBeforeDateType(); + beforeDate.length= strlen((char *) beforeDate.data) + 1; + afterDate.data= (unsigned char *) cd.GetAfterDate(); + afterDate.type= cd.GetAfterDateType(); + afterDate.length= strlen((char *) afterDate.data) + 1; + selfX509_ = NEW_YS X509(cd.GetIssuer(), iSz, cd.GetCommonName(), + sSz, &beforeDate, &afterDate, + cd.GetIssuerCnStart(), cd.GetIssuerCnLength(), + cd.GetSubjectCnStart(), cd.GetSubjectCnLength()); + } + return 0; +} + + +// Store OpenSSL type peer's cert +void CertManager::setPeerX509(X509* x) +{ + if (x == 0) return; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_STRING* before = x->GetBefore(); + ASN1_STRING* after = x->GetAfter(); + + peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), before, after, + issuer->GetCnPosition(), issuer->GetCnLength(), + subject->GetCnPosition(), subject->GetCnLength()); +} + + +#if defined(USE_CML_LIB) + +// Get the peer's certificate, extract and save public key +void CertManager::SetPeerKey() +{ + // first cert is the peer's + x509* main = peerList_.front(); + + Bytes_struct cert; + cert.num = main->get_length(); + cert.data = main->set_buffer(); + + CML::Certificate cm(cert); + const CML::ASN::Cert& raw = cm.base(); + CTIL::CSM_Buffer key = raw.pubKeyInfo.key; + + uint sz; + opaque* key_buffer = reinterpret_cast(key.Get(sz)); + peerPublicKey_.allocate(sz); + peerPublicKey_.assign(key_buffer, sz); +} + + +#endif // USE_CML_LIB + + + +} // namespace diff --git a/mysql/extra/yassl/src/crypto_wrapper.cpp b/mysql/extra/yassl/src/crypto_wrapper.cpp new file mode 100644 index 0000000..12f956e --- /dev/null +++ b/mysql/extra/yassl/src/crypto_wrapper.cpp @@ -0,0 +1,1016 @@ +/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +/* The crypto wrapper source implements the policies for the cipher + * components used by SSL. + * + * The implementation relies on a specfic library, taoCrypt. + */ + +#if !defined(USE_CRYPTOPP_LIB) + +#include "runtime.hpp" +#include "crypto_wrapper.hpp" +#include "cert_wrapper.hpp" + +#include "md5.hpp" +#include "sha.hpp" +#include "ripemd.hpp" +#include "hmac.hpp" +#include "modes.hpp" +#include "des.hpp" +#include "arc4.hpp" +#include "aes.hpp" +#include "rsa.hpp" +#include "dsa.hpp" +#include "dh.hpp" +#include "random.hpp" +#include "file.hpp" +#include "coding.hpp" + + +namespace yaSSL { + + +// MD5 Implementation +struct MD5::MD5Impl { + TaoCrypt::MD5 md5_; + MD5Impl() {} + explicit MD5Impl(const TaoCrypt::MD5& md5) : md5_(md5) {} +}; + + +MD5::MD5() : pimpl_(NEW_YS MD5Impl) {} + + +MD5::~MD5() { ysDelete(pimpl_); } + + +MD5::MD5(const MD5& that) : Digest(), pimpl_(NEW_YS + MD5Impl(that.pimpl_->md5_)) {} + + +MD5& MD5::operator=(const MD5& that) +{ + pimpl_->md5_ = that.pimpl_->md5_; + return *this; +} + + +uint MD5::get_digestSize() const +{ + return MD5_LEN; +} + + +uint MD5::get_padSize() const +{ + return PAD_MD5; +} + + +// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz +void MD5::get_digest(byte* out, const byte* in, unsigned int sz) +{ + pimpl_->md5_.Update(in, sz); + pimpl_->md5_.Final(out); +} + +// Fill out with MD5 digest from previous updates +void MD5::get_digest(byte* out) +{ + pimpl_->md5_.Final(out); +} + + +// Update the current digest +void MD5::update(const byte* in, unsigned int sz) +{ + pimpl_->md5_.Update(in, sz); +} + + +// SHA Implementation +struct SHA::SHAImpl { + TaoCrypt::SHA sha_; + SHAImpl() {} + explicit SHAImpl(const TaoCrypt::SHA& sha) : sha_(sha) {} +}; + + +SHA::SHA() : pimpl_(NEW_YS SHAImpl) {} + + +SHA::~SHA() { ysDelete(pimpl_); } + + +SHA::SHA(const SHA& that) : Digest(), pimpl_(NEW_YS SHAImpl(that.pimpl_->sha_)) {} + +SHA& SHA::operator=(const SHA& that) +{ + pimpl_->sha_ = that.pimpl_->sha_; + return *this; +} + + +uint SHA::get_digestSize() const +{ + return SHA_LEN; +} + + +uint SHA::get_padSize() const +{ + return PAD_SHA; +} + + +// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz +void SHA::get_digest(byte* out, const byte* in, unsigned int sz) +{ + pimpl_->sha_.Update(in, sz); + pimpl_->sha_.Final(out); +} + + +// Fill out with SHA digest from previous updates +void SHA::get_digest(byte* out) +{ + pimpl_->sha_.Final(out); +} + + +// Update the current digest +void SHA::update(const byte* in, unsigned int sz) +{ + pimpl_->sha_.Update(in, sz); +} + + +// RMD-160 Implementation +struct RMD::RMDImpl { + TaoCrypt::RIPEMD160 rmd_; + RMDImpl() {} + explicit RMDImpl(const TaoCrypt::RIPEMD160& rmd) : rmd_(rmd) {} +}; + + +RMD::RMD() : pimpl_(NEW_YS RMDImpl) {} + + +RMD::~RMD() { ysDelete(pimpl_); } + + +RMD::RMD(const RMD& that) : Digest(), pimpl_(NEW_YS RMDImpl(that.pimpl_->rmd_)) {} + +RMD& RMD::operator=(const RMD& that) +{ + pimpl_->rmd_ = that.pimpl_->rmd_; + return *this; +} + + +uint RMD::get_digestSize() const +{ + return RMD_LEN; +} + + +uint RMD::get_padSize() const +{ + return PAD_RMD; +} + + +// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz +void RMD::get_digest(byte* out, const byte* in, unsigned int sz) +{ + pimpl_->rmd_.Update(in, sz); + pimpl_->rmd_.Final(out); +} + + +// Fill out with RMD digest from previous updates +void RMD::get_digest(byte* out) +{ + pimpl_->rmd_.Final(out); +} + + +// Update the current digest +void RMD::update(const byte* in, unsigned int sz) +{ + pimpl_->rmd_.Update(in, sz); +} + + +// HMAC_MD5 Implementation +struct HMAC_MD5::HMAC_MD5Impl { + TaoCrypt::HMAC mac_; + HMAC_MD5Impl() {} +}; + + +HMAC_MD5::HMAC_MD5(const byte* secret, unsigned int len) + : pimpl_(NEW_YS HMAC_MD5Impl) +{ + pimpl_->mac_.SetKey(secret, len); +} + + +HMAC_MD5::~HMAC_MD5() { ysDelete(pimpl_); } + + +uint HMAC_MD5::get_digestSize() const +{ + return MD5_LEN; +} + + +uint HMAC_MD5::get_padSize() const +{ + return PAD_MD5; +} + + +// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz +void HMAC_MD5::get_digest(byte* out, const byte* in, unsigned int sz) +{ + pimpl_->mac_.Update(in, sz); + pimpl_->mac_.Final(out); +} + +// Fill out with MD5 digest from previous updates +void HMAC_MD5::get_digest(byte* out) +{ + pimpl_->mac_.Final(out); +} + + +// Update the current digest +void HMAC_MD5::update(const byte* in, unsigned int sz) +{ + pimpl_->mac_.Update(in, sz); +} + + +// HMAC_SHA Implementation +struct HMAC_SHA::HMAC_SHAImpl { + TaoCrypt::HMAC mac_; + HMAC_SHAImpl() {} +}; + + +HMAC_SHA::HMAC_SHA(const byte* secret, unsigned int len) + : pimpl_(NEW_YS HMAC_SHAImpl) +{ + pimpl_->mac_.SetKey(secret, len); +} + + +HMAC_SHA::~HMAC_SHA() { ysDelete(pimpl_); } + + +uint HMAC_SHA::get_digestSize() const +{ + return SHA_LEN; +} + + +uint HMAC_SHA::get_padSize() const +{ + return PAD_SHA; +} + + +// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz +void HMAC_SHA::get_digest(byte* out, const byte* in, unsigned int sz) +{ + pimpl_->mac_.Update(in, sz); + pimpl_->mac_.Final(out); +} + +// Fill out with SHA digest from previous updates +void HMAC_SHA::get_digest(byte* out) +{ + pimpl_->mac_.Final(out); +} + + +// Update the current digest +void HMAC_SHA::update(const byte* in, unsigned int sz) +{ + pimpl_->mac_.Update(in, sz); +} + + + +// HMAC_RMD Implementation +struct HMAC_RMD::HMAC_RMDImpl { + TaoCrypt::HMAC mac_; + HMAC_RMDImpl() {} +}; + + +HMAC_RMD::HMAC_RMD(const byte* secret, unsigned int len) + : pimpl_(NEW_YS HMAC_RMDImpl) +{ + pimpl_->mac_.SetKey(secret, len); +} + + +HMAC_RMD::~HMAC_RMD() { ysDelete(pimpl_); } + + +uint HMAC_RMD::get_digestSize() const +{ + return RMD_LEN; +} + + +uint HMAC_RMD::get_padSize() const +{ + return PAD_RMD; +} + + +// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz +void HMAC_RMD::get_digest(byte* out, const byte* in, unsigned int sz) +{ + pimpl_->mac_.Update(in, sz); + pimpl_->mac_.Final(out); +} + +// Fill out with RMD digest from previous updates +void HMAC_RMD::get_digest(byte* out) +{ + pimpl_->mac_.Final(out); +} + + +// Update the current digest +void HMAC_RMD::update(const byte* in, unsigned int sz) +{ + pimpl_->mac_.Update(in, sz); +} + + +struct DES::DESImpl { + TaoCrypt::DES_CBC_Encryption encryption; + TaoCrypt::DES_CBC_Decryption decryption; +}; + + +DES::DES() : pimpl_(NEW_YS DESImpl) {} + +DES::~DES() { ysDelete(pimpl_); } + + +void DES::set_encryptKey(const byte* k, const byte* iv) +{ + pimpl_->encryption.SetKey(k, DES_KEY_SZ, iv); +} + + +void DES::set_decryptKey(const byte* k, const byte* iv) +{ + pimpl_->decryption.SetKey(k, DES_KEY_SZ, iv); +} + +// DES encrypt plain of length sz into cipher +void DES::encrypt(byte* cipher, const byte* plain, unsigned int sz) +{ + pimpl_->encryption.Process(cipher, plain, sz); +} + + +// DES decrypt cipher of length sz into plain +void DES::decrypt(byte* plain, const byte* cipher, unsigned int sz) +{ + pimpl_->decryption.Process(plain, cipher, sz); +} + + +struct DES_EDE::DES_EDEImpl { + TaoCrypt::DES_EDE3_CBC_Encryption encryption; + TaoCrypt::DES_EDE3_CBC_Decryption decryption; +}; + + +DES_EDE::DES_EDE() : pimpl_(NEW_YS DES_EDEImpl) {} + +DES_EDE::~DES_EDE() { ysDelete(pimpl_); } + + +void DES_EDE::set_encryptKey(const byte* k, const byte* iv) +{ + pimpl_->encryption.SetKey(k, DES_EDE_KEY_SZ, iv); +} + + +void DES_EDE::set_decryptKey(const byte* k, const byte* iv) +{ + pimpl_->decryption.SetKey(k, DES_EDE_KEY_SZ, iv); +} + + +// 3DES encrypt plain of length sz into cipher +void DES_EDE::encrypt(byte* cipher, const byte* plain, unsigned int sz) +{ + pimpl_->encryption.Process(cipher, plain, sz); +} + + +// 3DES decrypt cipher of length sz into plain +void DES_EDE::decrypt(byte* plain, const byte* cipher, unsigned int sz) +{ + pimpl_->decryption.Process(plain, cipher, sz); +} + + +// Implementation of alledged RC4 +struct RC4::RC4Impl { + TaoCrypt::ARC4::Encryption encryption; + TaoCrypt::ARC4::Decryption decryption; +}; + + +RC4::RC4() : pimpl_(NEW_YS RC4Impl) {} + +RC4::~RC4() { ysDelete(pimpl_); } + + +void RC4::set_encryptKey(const byte* k, const byte*) +{ + pimpl_->encryption.SetKey(k, RC4_KEY_SZ); +} + + +void RC4::set_decryptKey(const byte* k, const byte*) +{ + pimpl_->decryption.SetKey(k, RC4_KEY_SZ); +} + + +// RC4 encrypt plain of length sz into cipher +void RC4::encrypt(byte* cipher, const byte* plain, unsigned int sz) +{ + pimpl_->encryption.Process(cipher, plain, sz); +} + + +// RC4 decrypt cipher of length sz into plain +void RC4::decrypt(byte* plain, const byte* cipher, unsigned int sz) +{ + pimpl_->decryption.Process(plain, cipher, sz); +} + + + +// Implementation of AES +struct AES::AESImpl { + TaoCrypt::AES_CBC_Encryption encryption; + TaoCrypt::AES_CBC_Decryption decryption; + unsigned int keySz_; + + AESImpl(unsigned int ks) : keySz_(ks) {} +}; + + +AES::AES(unsigned int ks) : pimpl_(NEW_YS AESImpl(ks)) {} + +AES::~AES() { ysDelete(pimpl_); } + + +int AES::get_keySize() const +{ + return pimpl_->keySz_; +} + + +void AES::set_encryptKey(const byte* k, const byte* iv) +{ + pimpl_->encryption.SetKey(k, pimpl_->keySz_, iv); +} + + +void AES::set_decryptKey(const byte* k, const byte* iv) +{ + pimpl_->decryption.SetKey(k, pimpl_->keySz_, iv); +} + + +// AES encrypt plain of length sz into cipher +void AES::encrypt(byte* cipher, const byte* plain, unsigned int sz) +{ + pimpl_->encryption.Process(cipher, plain, sz); +} + + +// AES decrypt cipher of length sz into plain +void AES::decrypt(byte* plain, const byte* cipher, unsigned int sz) +{ + pimpl_->decryption.Process(plain, cipher, sz); +} + + +struct RandomPool::RandomImpl { + TaoCrypt::RandomNumberGenerator RNG_; +}; + +RandomPool::RandomPool() : pimpl_(NEW_YS RandomImpl) {} + +RandomPool::~RandomPool() { ysDelete(pimpl_); } + +int RandomPool::GetError() const +{ + return pimpl_->RNG_.GetError(); +} + +void RandomPool::Fill(opaque* dst, uint sz) const +{ + pimpl_->RNG_.GenerateBlock(dst, sz); +} + + +// Implementation of DSS Authentication +struct DSS::DSSImpl { + void SetPublic (const byte*, unsigned int); + void SetPrivate(const byte*, unsigned int); + TaoCrypt::DSA_PublicKey publicKey_; + TaoCrypt::DSA_PrivateKey privateKey_; +}; + + +// Decode and store the public key +void DSS::DSSImpl::SetPublic(const byte* key, unsigned int sz) +{ + TaoCrypt::Source source(key, sz); + publicKey_.Initialize(source); +} + + +// Decode and store the public key +void DSS::DSSImpl::SetPrivate(const byte* key, unsigned int sz) +{ + TaoCrypt::Source source(key, sz); + privateKey_.Initialize(source); + publicKey_ = TaoCrypt::DSA_PublicKey(privateKey_); + +} + + +// Set public or private key +DSS::DSS(const byte* key, unsigned int sz, bool publicKey) + : pimpl_(NEW_YS DSSImpl) +{ + if (publicKey) + pimpl_->SetPublic(key, sz); + else + pimpl_->SetPrivate(key, sz); +} + + +DSS::~DSS() +{ + ysDelete(pimpl_); +} + + +uint DSS::get_signatureLength() const +{ + return pimpl_->publicKey_.SignatureLength(); +} + + +// DSS Sign message of length sz into sig +void DSS::sign(byte* sig, const byte* sha_digest, unsigned int /* shaSz */, + const RandomPool& random) +{ + using namespace TaoCrypt; + + DSA_Signer signer(pimpl_->privateKey_); + signer.Sign(sha_digest, sig, random.pimpl_->RNG_); +} + + +// DSS Verify message of length sz against sig, is it correct? +bool DSS::verify(const byte* sha_digest, unsigned int /* shaSz */, + const byte* sig, unsigned int /* sigSz */) +{ + using namespace TaoCrypt; + + DSA_Verifier ver(pimpl_->publicKey_); + return ver.Verify(sha_digest, sig); +} + + +// Implementation of RSA key interface +struct RSA::RSAImpl { + void SetPublic (const byte*, unsigned int); + void SetPrivate(const byte*, unsigned int); + TaoCrypt::RSA_PublicKey publicKey_; + TaoCrypt::RSA_PrivateKey privateKey_; +}; + + +// Decode and store the public key +void RSA::RSAImpl::SetPublic(const byte* key, unsigned int sz) +{ + TaoCrypt::Source source(key, sz); + publicKey_.Initialize(source); +} + + +// Decode and store the private key +void RSA::RSAImpl::SetPrivate(const byte* key, unsigned int sz) +{ + TaoCrypt::Source source(key, sz); + privateKey_.Initialize(source); + publicKey_ = TaoCrypt::RSA_PublicKey(privateKey_); +} + + +// Set public or private key +RSA::RSA(const byte* key, unsigned int sz, bool publicKey) + : pimpl_(NEW_YS RSAImpl) +{ + if (publicKey) + pimpl_->SetPublic(key, sz); + else + pimpl_->SetPrivate(key, sz); +} + +RSA::~RSA() +{ + ysDelete(pimpl_); +} + + +// get cipher text length, varies on key size +unsigned int RSA::get_cipherLength() const +{ + return pimpl_->publicKey_.FixedCiphertextLength(); +} + + +// get signautre length, varies on key size +unsigned int RSA::get_signatureLength() const +{ + return get_cipherLength(); +} + + +// RSA Sign message of length sz into sig +void RSA::sign(byte* sig, const byte* message, unsigned int sz, + const RandomPool& random) +{ + TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_); + dec.SSL_Sign(message, sz, sig, random.pimpl_->RNG_); +} + + +// RSA Verify message of length sz against sig +bool RSA::verify(const byte* message, unsigned int sz, const byte* sig, + unsigned int) +{ + TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_); + return enc.SSL_Verify(message, sz, sig); +} + + +// RSA public encrypt plain of length sz into cipher +void RSA::encrypt(byte* cipher, const byte* plain, unsigned int sz, + const RandomPool& random) +{ + + TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_); + enc.Encrypt(plain, sz, cipher, random.pimpl_->RNG_); +} + + +// RSA private decrypt cipher of length sz into plain +void RSA::decrypt(byte* plain, const byte* cipher, unsigned int sz, + const RandomPool& random) +{ + TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_); + dec.Decrypt(cipher, sz, plain, random.pimpl_->RNG_); +} + + +struct Integer::IntegerImpl { + TaoCrypt::Integer int_; + + IntegerImpl() {} + explicit IntegerImpl(const TaoCrypt::Integer& i) : int_(i) {} +}; + +Integer::Integer() : pimpl_(NEW_YS IntegerImpl) {} + +Integer::~Integer() { ysDelete(pimpl_); } + + + +Integer::Integer(const Integer& other) : pimpl_(NEW_YS + IntegerImpl(other.pimpl_->int_)) +{} + + +Integer& Integer::operator=(const Integer& that) +{ + pimpl_->int_ = that.pimpl_->int_; + + return *this; +} + + +void Integer::assign(const byte* num, unsigned int sz) +{ + pimpl_->int_ = TaoCrypt::Integer(num, sz); +} + + +struct DiffieHellman::DHImpl { + TaoCrypt::DH dh_; + TaoCrypt::RandomNumberGenerator& ranPool_; + byte* publicKey_; + byte* privateKey_; + byte* agreedKey_; + uint pubKeyLength_; + + DHImpl(TaoCrypt::RandomNumberGenerator& r) : ranPool_(r), publicKey_(0), + privateKey_(0), agreedKey_(0), pubKeyLength_(0) {} + ~DHImpl() + { + ysArrayDelete(agreedKey_); + ysArrayDelete(privateKey_); + ysArrayDelete(publicKey_); + } + + DHImpl(const DHImpl& that) : dh_(that.dh_), ranPool_(that.ranPool_), + publicKey_(0), privateKey_(0), agreedKey_(0), pubKeyLength_(0) + { + uint length = dh_.GetByteLength(); + AllocKeys(length, length, length); + } + + void AllocKeys(unsigned int pubSz, unsigned int privSz, unsigned int agrSz) + { + publicKey_ = NEW_YS byte[pubSz]; + privateKey_ = NEW_YS byte[privSz]; + agreedKey_ = NEW_YS byte[agrSz]; + } +}; + + + +/* +// server Side DH, server's view +DiffieHellman::DiffieHellman(const char* file, const RandomPool& random) + : pimpl_(NEW_YS DHImpl(random.pimpl_->RNG_)) +{ + using namespace TaoCrypt; + Source source; + FileSource(file, source); + if (source.size() == 0) + return; // TODO add error state, and force check + HexDecoder hd(source); + + pimpl_->dh_.Initialize(source); + + uint length = pimpl_->dh_.GetByteLength(); + + pimpl_->AllocKeys(length, length, length); + pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_, + pimpl_->publicKey_); +} +*/ + + +// server Side DH, client's view +DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g, + unsigned int gSz, const byte* pub, + unsigned int pubSz, const RandomPool& random) + : pimpl_(NEW_YS DHImpl(random.pimpl_->RNG_)) +{ + using TaoCrypt::Integer; + + pimpl_->dh_.Initialize(Integer(p, pSz).Ref(), Integer(g, gSz).Ref()); + pimpl_->publicKey_ = NEW_YS opaque[pimpl_->pubKeyLength_ = pubSz]; + memcpy(pimpl_->publicKey_, pub, pubSz); +} + + +// Server Side DH, server's view +DiffieHellman::DiffieHellman(const Integer& p, const Integer& g, + const RandomPool& random) +: pimpl_(NEW_YS DHImpl(random.pimpl_->RNG_)) +{ + using TaoCrypt::Integer; + + pimpl_->dh_.Initialize(p.pimpl_->int_, g.pimpl_->int_); + + uint length = pimpl_->dh_.GetByteLength(); + + pimpl_->AllocKeys(length, length, length); + pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_, + pimpl_->publicKey_); +} + +DiffieHellman::~DiffieHellman() { ysDelete(pimpl_); } + + +// Client side and view, use server that for p and g +DiffieHellman::DiffieHellman(const DiffieHellman& that) + : pimpl_(NEW_YS DHImpl(*that.pimpl_)) +{ + pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_, + pimpl_->publicKey_); +} + + +DiffieHellman& DiffieHellman::operator=(const DiffieHellman& that) +{ + pimpl_->dh_ = that.pimpl_->dh_; + pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_, + pimpl_->publicKey_); + return *this; +} + + +void DiffieHellman::makeAgreement(const byte* other, unsigned int otherSz) +{ + pimpl_->dh_.Agree(pimpl_->agreedKey_, pimpl_->privateKey_, other, otherSz); +} + + +uint DiffieHellman::get_agreedKeyLength() const +{ + return pimpl_->dh_.GetByteLength(); +} + + +const byte* DiffieHellman::get_agreedKey() const +{ + return pimpl_->agreedKey_; +} + +uint DiffieHellman::get_publicKeyLength() const +{ + return pimpl_->pubKeyLength_; +} + +const byte* DiffieHellman::get_publicKey() const +{ + return pimpl_->publicKey_; +} + + +void DiffieHellman::set_sizes(int& pSz, int& gSz, int& pubSz) const +{ + using TaoCrypt::Integer; + Integer p = pimpl_->dh_.GetP(); + Integer g = pimpl_->dh_.GetG(); + + pSz = p.ByteCount(); + gSz = g.ByteCount(); + pubSz = pimpl_->dh_.GetByteLength(); +} + + +void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const +{ + using TaoCrypt::Integer; + Integer p = pimpl_->dh_.GetP(); + Integer g = pimpl_->dh_.GetG(); + + p.Encode(bp, p.ByteCount()); + g.Encode(bg, g.ByteCount()); + memcpy(bpub, pimpl_->publicKey_, pimpl_->dh_.GetByteLength()); +} + + +// convert PEM file to DER x509 type +x509* PemToDer(FILE* file, CertType type, EncryptedInfo* info) +{ + using namespace TaoCrypt; + + char header[80]; + char footer[80]; + + if (type == Cert) { + strncpy(header, "-----BEGIN CERTIFICATE-----", sizeof(header)); + strncpy(footer, "-----END CERTIFICATE-----", sizeof(footer)); + } else { + strncpy(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header)); + strncpy(footer, "-----END RSA PRIVATE KEY-----", sizeof(header)); + } + + long begin = -1; + long end = 0; + bool foundEnd = false; + + char line[80]; + + while(fgets(line, sizeof(line), file)) + if (strncmp(header, line, strlen(header)) == 0) { + begin = ftell(file); + break; + } + + // remove encrypted header if there + if (fgets(line, sizeof(line), file)) { + char encHeader[] = "Proc-Type"; + if (strncmp(encHeader, line, strlen(encHeader)) == 0 && + fgets(line,sizeof(line), file)) { + + char* start = strstr(line, "DES"); + char* finish = strstr(line, ","); + if (!start) + start = strstr(line, "AES"); + + if (!info) return 0; + + if ( start && finish && (start < finish)) { + memcpy(info->name, start, finish - start); + info->name[finish - start] = 0; + memcpy(info->iv, finish + 1, sizeof(info->iv)); + + char* newline = strstr(line, "\r"); + if (!newline) newline = strstr(line, "\n"); + if (newline && (newline > finish)) { + info->ivSz = newline - (finish + 1); + info->set = true; + } + } + begin = ftell(file); + if (fgets(line,sizeof(line), file)) // get blank line + begin = ftell(file); + } + + } + + while(fgets(line, sizeof(line), file)) + if (strncmp(footer, line, strlen(footer)) == 0) { + foundEnd = true; + break; + } + else + end = ftell(file); + + if (begin == -1 || !foundEnd) + return 0; + + input_buffer tmp(end - begin); + fseek(file, begin, SEEK_SET); + size_t bytes = fread(tmp.get_buffer(), end - begin, 1, file); + if (bytes != 1) + return 0; + + Source der(tmp.get_buffer(), end - begin); + Base64Decoder b64Dec(der); + + uint sz = der.size(); + mySTL::auto_ptr x(NEW_YS x509(sz)); + memcpy(x->use_buffer(), der.get_buffer(), sz); + + return x.release(); +} + + +} // namespace + + +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION +namespace yaSSL { +template void ysDelete(DiffieHellman::DHImpl*); +template void ysDelete(Integer::IntegerImpl*); +template void ysDelete(RSA::RSAImpl*); +template void ysDelete(DSS::DSSImpl*); +template void ysDelete(RandomPool::RandomImpl*); +template void ysDelete(AES::AESImpl*); +template void ysDelete(RC4::RC4Impl*); +template void ysDelete(DES_EDE::DES_EDEImpl*); +template void ysDelete(DES::DESImpl*); +template void ysDelete(HMAC_RMD::HMAC_RMDImpl*); +template void ysDelete(HMAC_SHA::HMAC_SHAImpl*); +template void ysDelete(HMAC_MD5::HMAC_MD5Impl*); +template void ysDelete(RMD::RMDImpl*); +template void ysDelete(SHA::SHAImpl*); +template void ysDelete(MD5::MD5Impl*); +} +#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION + +#endif // !USE_CRYPTOPP_LIB diff --git a/mysql/extra/yassl/src/get_password.c b/mysql/extra/yassl/src/get_password.c new file mode 100644 index 0000000..65e5763 --- /dev/null +++ b/mysql/extra/yassl/src/get_password.c @@ -0,0 +1,218 @@ +/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* +** Ask for a password from tty +** This is an own file to avoid conflicts with curses +*/ +#include +#include +#include "mysql.h" +#include +#include +#include + +#ifdef HAVE_GETPASS +#ifdef HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ +#else /* ! HAVE_GETPASS */ +#ifndef _WIN32 +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_TERMIOS_H /* For tty-password */ +#include +#define TERMIO struct termios +#else +#ifdef HAVE_TERMIO_H /* For tty-password */ +#include +#define TERMIO struct termio +#else +#include +#define TERMIO struct sgttyb +#endif +#endif +#else +#include +#endif /* _WIN32 */ +#endif /* HAVE_GETPASS */ + +#ifdef HAVE_GETPASSPHRASE /* For Solaris */ +#define getpass(A) getpassphrase(A) +#endif + +#ifdef _WIN32 +/* were just going to fake it here and get input from + the keyboard */ + +char *get_tty_password_ext(const char *opt_message, + strdup_handler_t strdup_function) +{ + char to[80]; + char *pos=to,*end=to+sizeof(to)-1; + int i=0; + DBUG_ENTER("get_tty_password_ext"); + _cputs(opt_message ? opt_message : "Enter password: "); + for (;;) + { + char tmp; + tmp=_getch(); + if (tmp == '\b' || (int) tmp == 127) + { + if (pos != to) + { + _cputs("\b \b"); + pos--; + continue; + } + } + if (tmp == '\n' || tmp == '\r' || tmp == 3) + break; + if (iscntrl(tmp) || pos == end) + continue; + _cputs("*"); + *(pos++) = tmp; + } + while (pos != to && isspace(pos[-1]) == ' ') + pos--; /* Allow dummy space at end */ + *pos=0; + _cputs("\n"); + DBUG_RETURN(strdup_function(to,MYF(MY_FAE))); +} + +#else + + +#ifndef HAVE_GETPASS +/* +** Can't use fgets, because readline will get confused +** length is max number of chars in to, not counting \0 +* to will not include the eol characters. +*/ + +static void get_password(char *to,uint length,int fd, my_bool echo) +{ + char *pos=to,*end=to+length; + + for (;;) + { + char tmp; + if (my_read(fd,&tmp,1,MYF(0)) != 1) + break; + if (tmp == '\b' || (int) tmp == 127) + { + if (pos != to) + { + if (echo) + { + fputs("\b \b",stderr); + fflush(stderr); + } + pos--; + continue; + } + } + if (tmp == '\n' || tmp == '\r' || tmp == 3) + break; + if (iscntrl(tmp) || pos == end) + continue; + if (echo) + { + fputc('*',stderr); + fflush(stderr); + } + *(pos++) = tmp; + } + while (pos != to && isspace(pos[-1]) == ' ') + pos--; /* Allow dummy space at end */ + *pos=0; + return; +} + +#endif /* ! HAVE_GETPASS */ + + +char *get_tty_password_ext(const char *opt_message, + strdup_handler_t strdup_function) +{ +#ifdef HAVE_GETPASS + char *passbuff; +#else /* ! HAVE_GETPASS */ + TERMIO org,tmp; +#endif /* HAVE_GETPASS */ + char buff[80]; + + DBUG_ENTER("get_tty_password_ext"); + +#ifdef HAVE_GETPASS + passbuff = getpass(opt_message ? opt_message : "Enter password: "); + + /* copy the password to buff and clear original (static) buffer */ + my_stpnmov(buff, passbuff, sizeof(buff) - 1); +#ifdef _PASSWORD_LEN + memset(passbuff, 0, _PASSWORD_LEN); +#endif +#else + if (isatty(fileno(stderr))) + { + fputs(opt_message ? opt_message : "Enter password: ",stderr); + fflush(stderr); + } +#if defined(HAVE_TERMIOS_H) + tcgetattr(fileno(stdin), &org); + tmp = org; + tmp.c_lflag &= ~(ECHO | ISIG | ICANON); + tmp.c_cc[VMIN] = 1; + tmp.c_cc[VTIME] = 0; + tcsetattr(fileno(stdin), TCSADRAIN, &tmp); + get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stderr))); + tcsetattr(fileno(stdin), TCSADRAIN, &org); +#elif defined(HAVE_TERMIO_H) + ioctl(fileno(stdin), (int) TCGETA, &org); + tmp=org; + tmp.c_lflag &= ~(ECHO | ISIG | ICANON); + tmp.c_cc[VMIN] = 1; + tmp.c_cc[VTIME]= 0; + ioctl(fileno(stdin),(int) TCSETA, &tmp); + get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr))); + ioctl(fileno(stdin),(int) TCSETA, &org); +#else + gtty(fileno(stdin), &org); + tmp=org; + tmp.sg_flags &= ~ECHO; + tmp.sg_flags |= RAW; + stty(fileno(stdin), &tmp); + get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr))); + stty(fileno(stdin), &org); +#endif + if (isatty(fileno(stderr))) + fputc('\n',stderr); +#endif /* HAVE_GETPASS */ + + DBUG_RETURN(strdup_function(buff,MYF(MY_FAE))); +} + +#endif /* _WIN32 */ + +static char * my_strdup_fct(const char *str, myf flags) +{ + return my_strdup(PSI_NOT_INSTRUMENTED, str, flags); +} + +char *get_tty_password(const char *opt_message) +{ + return get_tty_password_ext(opt_message, my_strdup_fct); +} diff --git a/mysql/extra/yassl/src/handshake.cpp b/mysql/extra/yassl/src/handshake.cpp new file mode 100644 index 0000000..91cc407 --- /dev/null +++ b/mysql/extra/yassl/src/handshake.cpp @@ -0,0 +1,1190 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* The handshake source implements functions for creating and reading + * the various handshake messages. + */ + + + +#include "runtime.hpp" +#include "handshake.hpp" +#include "yassl_int.hpp" + + +namespace yaSSL { + + + +// Build a client hello message from cipher suites and compression method +void buildClientHello(SSL& ssl, ClientHello& hello) +{ + // store for pre master secret + ssl.useSecurity().use_connection().chVersion_ = hello.client_version_; + + ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN); + if (ssl.getSecurity().get_resuming()) { + hello.id_len_ = ID_LEN; + memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(), + ID_LEN); + } + else + hello.id_len_ = 0; + hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_; + memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_, + hello.suite_len_); + hello.comp_len_ = 1; + + hello.set_length(sizeof(ProtocolVersion) + + RAN_LEN + + hello.id_len_ + sizeof(hello.id_len_) + + hello.suite_len_ + sizeof(hello.suite_len_) + + hello.comp_len_ + sizeof(hello.comp_len_)); +} + + +// Build a server hello message +void buildServerHello(SSL& ssl, ServerHello& hello) +{ + if (ssl.getSecurity().get_resuming()) { + memcpy(hello.random_,ssl.getSecurity().get_connection().server_random_, + RAN_LEN); + memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(), + ID_LEN); + } + else { + ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN); + ssl.getCrypto().get_random().Fill(hello.session_id_, ID_LEN); + } + hello.id_len_ = ID_LEN; + ssl.set_sessionID(hello.session_id_); + + hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0]; + hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1]; + hello.compression_method_ = hello.compression_method_; + + hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN + + sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM); +} + + +// add handshake from buffer into md5 and sha hashes, use handshake header +void hashHandShake(SSL& ssl, const input_buffer& input, uint sz) +{ + const opaque* buffer = input.get_buffer() + input.get_current() - + HANDSHAKE_HEADER; + sz += HANDSHAKE_HEADER; + ssl.useHashes().use_MD5().update(buffer, sz); + ssl.useHashes().use_SHA().update(buffer, sz); +} + + +// locals +namespace { + +// Write a plaintext record to buffer +void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr, + const Message& msg) +{ + buffer.allocate(RECORD_HEADER + rlHdr.length_); + buffer << rlHdr << msg; +} + + +// Write a plaintext record to buffer +void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr, + const HandShakeHeader& hsHdr, const HandShakeBase& shake) +{ + buffer.allocate(RECORD_HEADER + rlHdr.length_); + buffer << rlHdr << hsHdr << shake; +} + + +// Build Record Layer header for Message without handshake header +void buildHeader(SSL& ssl, RecordLayerHeader& rlHeader, const Message& msg) +{ + ProtocolVersion pv = ssl.getSecurity().get_connection().version_; + rlHeader.type_ = msg.get_type(); + rlHeader.version_.major_ = pv.major_; + rlHeader.version_.minor_ = pv.minor_; + rlHeader.length_ = msg.get_length(); +} + + +// Build HandShake and RecordLayer Headers for handshake output +void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader, + RecordLayerHeader& rlHeader, const HandShakeBase& shake) +{ + int sz = shake.get_length(); + + hsHeader.set_type(shake.get_type()); + hsHeader.set_length(sz); + + ProtocolVersion pv = ssl.getSecurity().get_connection().version_; + rlHeader.type_ = handshake; + rlHeader.version_.major_ = pv.major_; + rlHeader.version_.minor_ = pv.minor_; + rlHeader.length_ = sz + HANDSHAKE_HEADER; +} + + +// add handshake from buffer into md5 and sha hashes, exclude record header +void hashHandShake(SSL& ssl, const output_buffer& output, bool removeIV = false) +{ + uint sz = output.get_size() - RECORD_HEADER; + + const opaque* buffer = output.get_buffer() + RECORD_HEADER; + + if (removeIV) { // TLSv1_1 IV + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + sz -= blockSz; + buffer += blockSz; + } + + ssl.useHashes().use_MD5().update(buffer, sz); + ssl.useHashes().use_SHA().update(buffer, sz); +} + + +// calculate MD5 hash for finished +void buildMD5(SSL& ssl, Finished& fin, const opaque* sender) +{ + + opaque md5_result[MD5_LEN]; + opaque md5_inner[SIZEOF_SENDER + SECRET_LEN + PAD_MD5]; + opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN]; + + const opaque* master_secret = + ssl.getSecurity().get_connection().master_secret_; + + // make md5 inner + memcpy(md5_inner, sender, SIZEOF_SENDER); + memcpy(&md5_inner[SIZEOF_SENDER], master_secret, SECRET_LEN); + memcpy(&md5_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_MD5); + + ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner, + sizeof(md5_inner)); + + // make md5 outer + memcpy(md5_outer, master_secret, SECRET_LEN); + memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5); + memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN); + + ssl.useHashes().use_MD5().get_digest(fin.set_md5(), md5_outer, + sizeof(md5_outer)); +} + + +// calculate SHA hash for finished +void buildSHA(SSL& ssl, Finished& fin, const opaque* sender) +{ + + opaque sha_result[SHA_LEN]; + opaque sha_inner[SIZEOF_SENDER + SECRET_LEN + PAD_SHA]; + opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN]; + + const opaque* master_secret = + ssl.getSecurity().get_connection().master_secret_; + + // make sha inner + memcpy(sha_inner, sender, SIZEOF_SENDER); + memcpy(&sha_inner[SIZEOF_SENDER], master_secret, SECRET_LEN); + memcpy(&sha_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_SHA); + + ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner, + sizeof(sha_inner)); + + // make sha outer + memcpy(sha_outer, master_secret, SECRET_LEN); + memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA); + memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN); + + ssl.useHashes().use_SHA().get_digest(fin.set_sha(), sha_outer, + sizeof(sha_outer)); +} + + +// sanity checks on encrypted message size +static int sanity_check_message(SSL& ssl, uint msgSz) +{ + uint minSz = 0; + + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + if (msgSz % blockSz) + return -1; + + minSz = ssl.getSecurity().get_parms().hash_size_ + 1; // pad byte too + if (blockSz > minSz) + minSz = blockSz; + + if (ssl.isTLSv1_1()) + minSz += blockSz; // explicit IV + } + else { // stream + minSz = ssl.getSecurity().get_parms().hash_size_; + } + + if (msgSz < minSz) + return -1; + + return 0; +} + + +// decrypt input message in place, store size in case needed later +void decrypt_message(SSL& ssl, input_buffer& input, uint sz) +{ + input_buffer plain(sz); + opaque* cipher = input.get_buffer() + input.get_current(); + + if (sanity_check_message(ssl, sz) != 0) { + ssl.SetError(sanityCipher_error); + return; + } + + ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz); + memcpy(cipher, plain.get_buffer(), sz); + ssl.useSecurity().use_parms().encrypt_size_ = sz; + + if (ssl.isTLSv1_1()) // IV + input.set_current(input.get_current() + + ssl.getCrypto().get_cipher().get_blockSize()); +} + + +// output operator for input_buffer +output_buffer& operator<<(output_buffer& output, const input_buffer& input) +{ + output.write(input.get_buffer(), input.get_size()); + return output; +} + + +// write headers, handshake hash, mac, pad, and encrypt +void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output) +{ + uint digestSz = ssl.getCrypto().get_digest().get_digestSize(); + uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ; + uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz; + uint pad = 0; + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + if (ssl.isTLSv1_1()) + sz += blockSz; // IV + sz += 1; // pad byte + pad = (sz - RECORD_HEADER) % blockSz; + pad = blockSz - pad; + sz += pad; + } + + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + buildHeaders(ssl, hsHeader, rlHeader, fin); + rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac + // and pad, hanshake doesn't + input_buffer iv; + if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){ + iv.allocate(blockSz); + ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz); + iv.add_size(blockSz); + } + uint ivSz = iv.get_size(); + output.allocate(sz); + output << rlHeader << iv << hsHeader << fin; + + hashHandShake(ssl, output, ssl.isTLSv1_1() ? true : false); + opaque digest[SHA_LEN]; // max size + if (ssl.isTLS()) + TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz, + output.get_size() - RECORD_HEADER - ivSz, handshake); + else + hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, + output.get_size() - RECORD_HEADER, handshake); + output.write(digest, digestSz); + + if (ssl.getSecurity().get_parms().cipher_type_ == block) + for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets + // pad value too + input_buffer cipher(rlHeader.length_); + ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(), + output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER); + output.set_current(RECORD_HEADER); + output.write(cipher.get_buffer(), cipher.get_capacity()); +} + + +// build an encrypted data or alert message for output +void buildMessage(SSL& ssl, output_buffer& output, const Message& msg) +{ + uint digestSz = ssl.getCrypto().get_digest().get_digestSize(); + uint sz = RECORD_HEADER + msg.get_length() + digestSz; + uint pad = 0; + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + if (ssl.isTLSv1_1()) // IV + sz += blockSz; + sz += 1; // pad byte + pad = (sz - RECORD_HEADER) % blockSz; + pad = blockSz - pad; + sz += pad; + } + + RecordLayerHeader rlHeader; + buildHeader(ssl, rlHeader, msg); + rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac + // and pad, hanshake doesn't + input_buffer iv; + if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){ + iv.allocate(blockSz); + ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz); + iv.add_size(blockSz); + } + + uint ivSz = iv.get_size(); + output.allocate(sz); + output << rlHeader << iv << msg; + + opaque digest[SHA_LEN]; // max size + if (ssl.isTLS()) + TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz, + output.get_size() - RECORD_HEADER - ivSz, msg.get_type()); + else + hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, + output.get_size() - RECORD_HEADER, msg.get_type()); + output.write(digest, digestSz); + + if (ssl.getSecurity().get_parms().cipher_type_ == block) + for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets + // pad value too + input_buffer cipher(rlHeader.length_); + ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(), + output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER); + output.set_current(RECORD_HEADER); + output.write(cipher.get_buffer(), cipher.get_capacity()); +} + + +// build alert message +void buildAlert(SSL& ssl, output_buffer& output, const Alert& alert) +{ + if (ssl.getSecurity().get_parms().pending_ == false) // encrypted + buildMessage(ssl, output, alert); + else { + RecordLayerHeader rlHeader; + buildHeader(ssl, rlHeader, alert); + buildOutput(output, rlHeader, alert); + } +} + + +// build TLS finished message +void buildFinishedTLS(SSL& ssl, Finished& fin, const opaque* sender) +{ + opaque handshake_hash[FINISHED_SZ]; + + ssl.useHashes().use_MD5().get_digest(handshake_hash); + ssl.useHashes().use_SHA().get_digest(&handshake_hash[MD5_LEN]); + + const opaque* side; + if ( strncmp((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; + + PRF(fin.set_md5(), TLS_FINISHED_SZ, + ssl.getSecurity().get_connection().master_secret_, SECRET_LEN, + side, FINISHED_LABEL_SZ, + handshake_hash, FINISHED_SZ); + + fin.set_length(TLS_FINISHED_SZ); // shorter length for TLS +} + + +// compute p_hash for MD5 or SHA-1 for TLSv1 PRF +void p_hash(output_buffer& result, const output_buffer& secret, + const output_buffer& seed, MACAlgorithm hash) +{ + uint len = hash == md5 ? MD5_LEN : SHA_LEN; + uint times = result.get_capacity() / len; + uint lastLen = result.get_capacity() % len; + opaque previous[SHA_LEN]; // max size + opaque current[SHA_LEN]; // max size + mySTL::auto_ptr hmac; + + if (lastLen) times += 1; + + if (hash == md5) + hmac.reset(NEW_YS HMAC_MD5(secret.get_buffer(), secret.get_size())); + else + hmac.reset(NEW_YS HMAC_SHA(secret.get_buffer(), secret.get_size())); + // A0 = seed + hmac->get_digest(previous, seed.get_buffer(), seed.get_size());// A1 + uint lastTime = times - 1; + + for (uint i = 0; i < times; i++) { + hmac->update(previous, len); + hmac->get_digest(current, seed.get_buffer(), seed.get_size()); + + if (lastLen && (i == lastTime)) + result.write(current, lastLen); + else { + result.write(current, len); + //memcpy(previous, current, len); + hmac->get_digest(previous, previous, len); + } + } +} + + +// calculate XOR for TLSv1 PRF +void get_xor(byte *digest, uint digLen, output_buffer& md5, + output_buffer& sha) +{ + for (uint i = 0; i < digLen; i++) + digest[i] = md5[AUTO] ^ sha[AUTO]; +} + + +// build MD5 part of certificate verify +void buildMD5_CertVerify(SSL& ssl, byte* digest) +{ + opaque md5_result[MD5_LEN]; + opaque md5_inner[SECRET_LEN + PAD_MD5]; + opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN]; + + const opaque* master_secret = + ssl.getSecurity().get_connection().master_secret_; + + // make md5 inner + memcpy(md5_inner, master_secret, SECRET_LEN); + memcpy(&md5_inner[SECRET_LEN], PAD1, PAD_MD5); + + ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner, + sizeof(md5_inner)); + + // make md5 outer + memcpy(md5_outer, master_secret, SECRET_LEN); + memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5); + memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN); + + ssl.useHashes().use_MD5().get_digest(digest, md5_outer, sizeof(md5_outer)); +} + + +// build SHA part of certificate verify +void buildSHA_CertVerify(SSL& ssl, byte* digest) +{ + opaque sha_result[SHA_LEN]; + opaque sha_inner[SECRET_LEN + PAD_SHA]; + opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN]; + + const opaque* master_secret = + ssl.getSecurity().get_connection().master_secret_; + + // make sha inner + memcpy(sha_inner, master_secret, SECRET_LEN); + memcpy(&sha_inner[SECRET_LEN], PAD1, PAD_SHA); + + ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner, + sizeof(sha_inner)); + + // make sha outer + memcpy(sha_outer, master_secret, SECRET_LEN); + memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA); + memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN); + + ssl.useHashes().use_SHA().get_digest(digest, sha_outer, sizeof(sha_outer)); +} + + +} // namespace for locals + + +// some clients still send sslv2 client hello +void ProcessOldClientHello(input_buffer& input, SSL& ssl) +{ + if (input.get_error() || input.get_remaining() < 2) { + ssl.SetError(bad_input); + return; + } + byte b0 = input[AUTO]; + byte b1 = input[AUTO]; + + uint16 sz = ((b0 & 0x7f) << 8) | b1; + + if (sz > input.get_remaining()) { + ssl.SetError(bad_input); + return; + } + + // hashHandShake manually + const opaque* buffer = input.get_buffer() + input.get_current(); + ssl.useHashes().use_MD5().update(buffer, sz); + ssl.useHashes().use_SHA().update(buffer, sz); + + b1 = input[AUTO]; // does this value mean client_hello? + + ClientHello ch; + ch.client_version_.major_ = input[AUTO]; + ch.client_version_.minor_ = input[AUTO]; + + byte len[2]; + + len[0] = input[AUTO]; + len[1] = input[AUTO]; + ato16(len, ch.suite_len_); + + len[0] = input[AUTO]; + len[1] = input[AUTO]; + uint16 sessionLen; + ato16(len, sessionLen); + ch.id_len_ = sessionLen; + + len[0] = input[AUTO]; + len[1] = input[AUTO]; + uint16 randomLen; + ato16(len, randomLen); + + if (input.get_error() || ch.suite_len_ > MAX_SUITE_SZ || + ch.suite_len_ > input.get_remaining() || + sessionLen > ID_LEN || randomLen > RAN_LEN) { + ssl.SetError(bad_input); + return; + } + + int j = 0; + for (uint16 i = 0; i < ch.suite_len_; i += 3) { + byte first = input[AUTO]; + if (first) // sslv2 type + input.read(len, SUITE_LEN); // skip + else { + input.read(&ch.cipher_suites_[j], SUITE_LEN); + j += SUITE_LEN; + } + } + ch.suite_len_ = j; + + if (ch.id_len_) + input.read(ch.session_id_, ch.id_len_); // id_len_ from sessionLen + + if (randomLen < RAN_LEN) + memset(ch.random_, 0, RAN_LEN - randomLen); + input.read(&ch.random_[RAN_LEN - randomLen], randomLen); + + ch.Process(input, ssl); +} + + +// Build a finished message, see 7.6.9 +void buildFinished(SSL& ssl, Finished& fin, const opaque* sender) +{ + // store current states, building requires get_digest which resets state + MD5 md5(ssl.getHashes().get_MD5()); + SHA sha(ssl.getHashes().get_SHA()); + + if (ssl.isTLS()) + buildFinishedTLS(ssl, fin, sender); + else { + buildMD5(ssl, fin, sender); + buildSHA(ssl, fin, sender); + } + + // restore + ssl.useHashes().use_MD5() = md5; + ssl.useHashes().use_SHA() = sha; +} + + +/* compute SSLv3 HMAC into digest see + * buffer is of sz size and includes HandShake Header but not a Record Header + * verify means to check peers hmac +*/ +void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz, + ContentType content, bool verify) +{ + Digest& mac = ssl.useCrypto().use_digest(); + opaque inner[SHA_LEN + PAD_MD5 + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ]; + opaque outer[SHA_LEN + PAD_MD5 + SHA_LEN]; + opaque result[SHA_LEN]; // max possible sizes + uint digestSz = mac.get_digestSize(); // actual sizes + uint padSz = mac.get_padSize(); + uint innerSz = digestSz + padSz + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ; + uint outerSz = digestSz + padSz + digestSz; + + // data + const opaque* mac_secret = ssl.get_macSecret(verify); + opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 }; + opaque length[LENGTH_SZ]; + c16toa(sz, length); + c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]); + + // make inner + memcpy(inner, mac_secret, digestSz); + memcpy(&inner[digestSz], PAD1, padSz); + memcpy(&inner[digestSz + padSz], seq, SEQ_SZ); + inner[digestSz + padSz + SEQ_SZ] = content; + memcpy(&inner[digestSz + padSz + SEQ_SZ + SIZEOF_ENUM], length, LENGTH_SZ); + + mac.update(inner, innerSz); + mac.get_digest(result, buffer, sz); // append content buffer + + // make outer + memcpy(outer, mac_secret, digestSz); + memcpy(&outer[digestSz], PAD2, padSz); + memcpy(&outer[digestSz + padSz], result, digestSz); + + mac.get_digest(digest, outer, outerSz); +} + + +// TLS type HAMC +void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz, + ContentType content, bool verify) +{ + mySTL::auto_ptr hmac; + opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 }; + opaque length[LENGTH_SZ]; + opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len + + c16toa(sz, length); + c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]); + + MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_; + + if (algo == sha) + hmac.reset(NEW_YS HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN)); + else if (algo == rmd) + hmac.reset(NEW_YS HMAC_RMD(ssl.get_macSecret(verify), RMD_LEN)); + else + hmac.reset(NEW_YS HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN)); + + hmac->update(seq, SEQ_SZ); // seq_num + inner[0] = content; // type + inner[SIZEOF_ENUM] = ssl.getSecurity().get_connection().version_.major_; + inner[SIZEOF_ENUM + SIZEOF_ENUM] = + ssl.getSecurity().get_connection().version_.minor_; // version + memcpy(&inner[SIZEOF_ENUM + VERSION_SZ], length, LENGTH_SZ); // length + hmac->update(inner, sizeof(inner)); + hmac->get_digest(digest, buffer, sz); // content +} + + +// compute TLSv1 PRF (pseudo random function using HMAC) +void PRF(byte* digest, uint digLen, const byte* secret, uint secLen, + const byte* label, uint labLen, const byte* seed, uint seedLen) +{ + uint half = (secLen + 1) / 2; + + output_buffer md5_half(half); + output_buffer sha_half(half); + output_buffer labelSeed(labLen + seedLen); + + md5_half.write(secret, half); + sha_half.write(secret + half - secLen % 2, half); + labelSeed.write(label, labLen); + labelSeed.write(seed, seedLen); + + output_buffer md5_result(digLen); + output_buffer sha_result(digLen); + + p_hash(md5_result, md5_half, labelSeed, md5); + p_hash(sha_result, sha_half, labelSeed, sha); + + md5_result.set_current(0); + sha_result.set_current(0); + get_xor(digest, digLen, md5_result, sha_result); +} + + +// build certificate hashes +void build_certHashes(SSL& ssl, Hashes& hashes) +{ + // store current states, building requires get_digest which resets state + MD5 md5(ssl.getHashes().get_MD5()); + SHA sha(ssl.getHashes().get_SHA()); + + if (ssl.isTLS()) { + ssl.useHashes().use_MD5().get_digest(hashes.md5_); + ssl.useHashes().use_SHA().get_digest(hashes.sha_); + } + else { + buildMD5_CertVerify(ssl, hashes.md5_); + buildSHA_CertVerify(ssl, hashes.sha_); + } + + // restore + ssl.useHashes().use_MD5() = md5; + ssl.useHashes().use_SHA() = sha; +} + + + +// do process input requests, return 0 is done, 1 is call again to complete +int DoProcessReply(SSL& ssl) +{ + uint ready = ssl.getSocket().get_ready(); + if (!ready) + ready= 64; + + // add buffered data if its there + input_buffer* buffered = ssl.useBuffers().TakeRawInput(); + uint buffSz = buffered ? buffered->get_size() : 0; + input_buffer buffer(buffSz + ready); + if (buffSz) { + buffer.assign(buffered->get_buffer(), buffSz); + ysDelete(buffered); + buffered = 0; + } + + // add new data + uint read = ssl.useSocket().receive(buffer.get_buffer() + buffSz, ready); + if (read == static_cast(-1)) { + ssl.SetError(receive_error); + return 0; + } else if (read == 0) + return 1; + + buffer.add_size(read); + uint offset = 0; + const MessageFactory& mf = ssl.getFactory().getMessage(); + + // old style sslv2 client hello? + if (ssl.getSecurity().get_parms().entity_ == server_end && + ssl.getStates().getServer() == clientNull) + if (buffer.peek() != handshake) { + ProcessOldClientHello(buffer, ssl); + if (ssl.GetError()) + return 0; + } + + while(!buffer.eof()) { + // each record + RecordLayerHeader hdr; + bool needHdr = false; + + if (static_cast(RECORD_HEADER) > buffer.get_remaining()) + needHdr = true; + else { + buffer >> hdr; + ssl.verifyState(hdr); + } + + if (ssl.GetError()) + return 0; + + // make sure we have enough input in buffer to process this record + if (needHdr || hdr.length_ > buffer.get_remaining()) { + // put header in front for next time processing + uint extra = needHdr ? 0 : RECORD_HEADER; + uint sz = buffer.get_remaining() + extra; + ssl.useBuffers().SetRawInput(NEW_YS input_buffer(sz, + buffer.get_buffer() + buffer.get_current() - extra, sz)); + return 1; + } + + while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) { + // each message in record, can be more than 1 if not encrypted + if (ssl.GetError()) + return 0; + + if (ssl.getSecurity().get_parms().pending_ == false) { // cipher on + // sanity check for malicious/corrupted/illegal input + if (buffer.get_remaining() < hdr.length_) { + ssl.SetError(bad_input); + return 0; + } + decrypt_message(ssl, buffer, hdr.length_); + if (ssl.GetError()) + return 0; + } + + mySTL::auto_ptr msg(mf.CreateObject(hdr.type_)); + if (!msg.get()) { + ssl.SetError(factory_error); + return 0; + } + buffer >> *msg; + msg->Process(buffer, ssl); + if (ssl.GetError()) + return 0; + } + offset += hdr.length_ + RECORD_HEADER; + } + return 0; +} + + +// process input requests +void processReply(SSL& ssl) +{ + if (ssl.GetError()) return; + + if (DoProcessReply(ssl)) { + // didn't complete process + if (!ssl.getSocket().IsNonBlocking()) { + // keep trying now, blocking ok + while (!ssl.GetError()) + if (DoProcessReply(ssl) == 0) break; + } + else + // user will have try again later, non blocking + ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); + } +} + + +// send client_hello, no buffering +void sendClientHello(SSL& ssl) +{ + ssl.verifyState(serverNull); + if (ssl.GetError()) return; + + ClientHello ch(ssl.getSecurity().get_connection().version_, + ssl.getSecurity().get_connection().compression_); + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + output_buffer out; + + buildClientHello(ssl, ch); + ssl.set_random(ch.get_random(), client_end); + buildHeaders(ssl, hsHeader, rlHeader, ch); + buildOutput(out, rlHeader, hsHeader, ch); + hashHandShake(ssl, out); + + ssl.Send(out.get_buffer(), out.get_size()); +} + + +// send client key exchange +void sendClientKeyExchange(SSL& ssl, BufferOutput buffer) +{ + ssl.verifyState(serverHelloDoneComplete); + if (ssl.GetError()) return; + + ClientKeyExchange ck(ssl); + ck.build(ssl); + ssl.makeMasterSecret(); + + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + buildHeaders(ssl, hsHeader, rlHeader, ck); + buildOutput(*out.get(), rlHeader, hsHeader, ck); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send server key exchange +void sendServerKeyExchange(SSL& ssl, BufferOutput buffer) +{ + if (ssl.GetError()) return; + ServerKeyExchange sk(ssl); + sk.build(ssl); + if (ssl.GetError()) return; + + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + buildHeaders(ssl, hsHeader, rlHeader, sk); + buildOutput(*out.get(), rlHeader, hsHeader, sk); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send change cipher +void sendChangeCipher(SSL& ssl, BufferOutput buffer) +{ + if (ssl.getSecurity().get_parms().entity_ == server_end) { + if (ssl.getSecurity().get_resuming()) + ssl.verifyState(clientKeyExchangeComplete); + else + ssl.verifyState(clientFinishedComplete); + } + if (ssl.GetError()) return; + + ChangeCipherSpec ccs; + RecordLayerHeader rlHeader; + buildHeader(ssl, rlHeader, ccs); + mySTL::auto_ptr out(NEW_YS output_buffer); + buildOutput(*out.get(), rlHeader, ccs); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send finished +void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) +{ + if (ssl.GetError()) return; + + Finished fin; + buildFinished(ssl, fin, side == client_end ? client : server); + mySTL::auto_ptr out(NEW_YS output_buffer); + cipherFinished(ssl, fin, *out.get()); // hashes handshake + + if (ssl.getSecurity().get_resuming()) { + if (side == server_end) + buildFinished(ssl, ssl.useHashes().use_verify(), client); // client + } + else { + if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) + GetSessions().add(ssl); // store session + if (side == client_end) + buildFinished(ssl, ssl.useHashes().use_verify(), server); // server + } + ssl.useSecurity().use_connection().CleanMaster(); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send data +int sendData(SSL& ssl, const void* buffer, int sz) +{ + int sent = 0; + + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl.SetError(no_error); + + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + ssl.SetError(no_error); + ssl.SendWriteBuffered(); + if (!ssl.GetError()) { + // advance sent to prvevious sent + plain size just sent + sent = ssl.useBuffers().prevSent + ssl.useBuffers().plainSz; + } + } + + ssl.verfiyHandShakeComplete(); + if (ssl.GetError()) return -1; + + for (;;) { + int len = min(sz - sent, MAX_RECORD_SIZE); + output_buffer out; + input_buffer tmp; + + Data data; + + if (sent == sz) break; + + if (ssl.CompressionOn()) { + if (Compress(static_cast(buffer) + sent, len, + tmp) == -1) { + ssl.SetError(compress_error); + return -1; + } + data.SetData(tmp.get_size(), tmp.get_buffer()); + } + else + data.SetData(len, static_cast(buffer) + sent); + + buildMessage(ssl, out, data); + ssl.Send(out.get_buffer(), out.get_size()); + + if (ssl.GetError()) { + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + ssl.useBuffers().plainSz = len; + ssl.useBuffers().prevSent = sent; + } + return -1; + } + sent += len; + } + ssl.useLog().ShowData(sent, true); + return sent; +} + + +// send alert +int sendAlert(SSL& ssl, const Alert& alert) +{ + output_buffer out; + buildAlert(ssl, out, alert); + ssl.Send(out.get_buffer(), out.get_size()); + + return alert.get_length(); +} + + +// process input data +int receiveData(SSL& ssl, Data& data, bool peek) +{ + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl.SetError(no_error); + + ssl.verfiyHandShakeComplete(); + if (ssl.GetError()) return -1; + + if (!ssl.HasData()) + processReply(ssl); + + if (peek) + ssl.PeekData(data); + else + ssl.fillData(data); + + ssl.useLog().ShowData(data.get_length()); + if (ssl.GetError()) return -1; + + if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) { + ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); + return SSL_WOULD_BLOCK; + } + return data.get_length(); +} + + +// send server hello +void sendServerHello(SSL& ssl, BufferOutput buffer) +{ + if (ssl.getSecurity().get_resuming()) + ssl.verifyState(clientKeyExchangeComplete); + else + ssl.verifyState(clientHelloComplete); + if (ssl.GetError()) return; + + ServerHello sh(ssl.getSecurity().get_connection().version_, + ssl.getSecurity().get_connection().compression_); + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + + buildServerHello(ssl, sh); + ssl.set_random(sh.get_random(), server_end); + buildHeaders(ssl, hsHeader, rlHeader, sh); + buildOutput(*out.get(), rlHeader, hsHeader, sh); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send server hello done +void sendServerHelloDone(SSL& ssl, BufferOutput buffer) +{ + if (ssl.GetError()) return; + + ServerHelloDone shd; + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + + buildHeaders(ssl, hsHeader, rlHeader, shd); + buildOutput(*out.get(), rlHeader, hsHeader, shd); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send certificate +void sendCertificate(SSL& ssl, BufferOutput buffer) +{ + if (ssl.GetError()) return; + + Certificate cert(ssl.getCrypto().get_certManager().get_cert()); + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + + buildHeaders(ssl, hsHeader, rlHeader, cert); + buildOutput(*out.get(), rlHeader, hsHeader, cert); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send certificate request +void sendCertificateRequest(SSL& ssl, BufferOutput buffer) +{ + if (ssl.GetError()) return; + + CertificateRequest request; + request.Build(); + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + + buildHeaders(ssl, hsHeader, rlHeader, request); + buildOutput(*out.get(), rlHeader, hsHeader, request); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +// send certificate verify +void sendCertificateVerify(SSL& ssl, BufferOutput buffer) +{ + if (ssl.GetError()) return; + + if(ssl.getCrypto().get_certManager().sendBlankCert()) return; + + CertificateVerify verify; + verify.Build(ssl); + if (ssl.GetError()) return; + + RecordLayerHeader rlHeader; + HandShakeHeader hsHeader; + mySTL::auto_ptr out(NEW_YS output_buffer); + + buildHeaders(ssl, hsHeader, rlHeader, verify); + buildOutput(*out.get(), rlHeader, hsHeader, verify); + hashHandShake(ssl, *out.get()); + + if (buffer == buffered) + ssl.addBuffer(out.release()); + else + ssl.Send(out->get_buffer(), out->get_size()); +} + + +} // namespace diff --git a/mysql/extra/yassl/src/lock.cpp b/mysql/extra/yassl/src/lock.cpp new file mode 100644 index 0000000..c74ea1c --- /dev/null +++ b/mysql/extra/yassl/src/lock.cpp @@ -0,0 +1,87 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* Locking functions + */ + +#include "runtime.hpp" +#include "lock.hpp" + + +namespace yaSSL { + + +#ifdef MULTI_THREADED + #ifdef _WIN32 + + Mutex::Mutex() + { + InitializeCriticalSection(&cs_); + } + + + Mutex::~Mutex() + { + DeleteCriticalSection(&cs_); + } + + + Mutex::Lock::Lock(Mutex& lm) : mutex_(lm) + { + EnterCriticalSection(&mutex_.cs_); + } + + + Mutex::Lock::~Lock() + { + LeaveCriticalSection(&mutex_.cs_); + } + + #else // _WIN32 + + Mutex::Mutex() + { + pthread_mutex_init(&mutex_, 0); + } + + + Mutex::~Mutex() + { + pthread_mutex_destroy(&mutex_); + } + + + Mutex::Lock::Lock(Mutex& lm) : mutex_(lm) + { + pthread_mutex_lock(&mutex_.mutex_); + } + + + Mutex::Lock::~Lock() + { + pthread_mutex_unlock(&mutex_.mutex_); + } + + + #endif // _WIN32 +#endif // MULTI_THREADED + + + +} // namespace yaSSL + diff --git a/mysql/extra/yassl/src/log.cpp b/mysql/extra/yassl/src/log.cpp new file mode 100644 index 0000000..2f112ac --- /dev/null +++ b/mysql/extra/yassl/src/log.cpp @@ -0,0 +1,147 @@ +/* + Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* Debug logging functions + */ + + +#include "runtime.hpp" +#include "log.hpp" + +#ifdef YASSL_LOG + #include + #include + #include +#endif + + + +namespace yaSSL { + + +#ifdef YASSL_LOG + + enum { MAX_MSG = 81 }; + + Log::Log(const char* str) + { + log_ = fopen(str, "w"); + Trace("********** Logger Attached **********"); + } + + + Log::~Log() + { + Trace("********** Logger Detached **********"); + fclose(log_); + } + + + // Trace a message + void Log::Trace(const char* str) + { + if (!log_) return; + + time_t clicks = time(0); + char timeStr[32]; + + memset(timeStr, 0, sizeof(timeStr)); + // get rid of newline + strncpy(timeStr, ctime(&clicks), sizeof(timeStr)); + unsigned int len = strlen(timeStr); + timeStr[len - 1] = 0; + + char msg[MAX_MSG]; + + strncpy(msg, timeStr, sizeof(timeStr)); + strncat(msg, ":", 1); + strncat(msg, str, MAX_MSG - sizeof(timeStr) - 2); + strncat(msg, "\n", 1); + msg[MAX_MSG - 1] = 0; + + fputs(msg, log_); + } + + + #if defined(_WIN32) || defined(__MACH__) || defined(__hpux__) + typedef int socklen_t; + #endif + + + // write tcp address + void Log::ShowTCP(socket_t fd, bool ended) + { + sockaddr_in peeraddr; + socklen_t len = sizeof(peeraddr); + if (getpeername(fd, (sockaddr*)&peeraddr, &len) != 0) + return; + + const char* p = reinterpret_cast(&peeraddr.sin_addr); + char msg[MAX_MSG]; + char number[16]; + + if (ended) + strncpy(msg, "yaSSL conn DONE w/ peer ", 26); + else + strncpy(msg, "yaSSL conn BEGUN w/ peer ", 26); + for (int i = 0; i < 4; ++i) { + sprintf(number, "%u", static_cast(p[i])); + strncat(msg, number, 8); + if (i < 3) + strncat(msg, ".", 1); + } + strncat(msg, " port ", 8); + sprintf(number, "%d", htons(peeraddr.sin_port)); + strncat(msg, number, 8); + + msg[MAX_MSG - 1] = 0; + Trace(msg); + } + + + // log processed data + void Log::ShowData(uint bytes, bool sent) + { + char msg[MAX_MSG]; + char number[16]; + + if (sent) + strncpy(msg, "Sent ", 10); + else + strncpy(msg, "Received ", 10); + sprintf(number, "%u", bytes); + strncat(msg, number, 8); + strncat(msg, " bytes of application data", 27); + + msg[MAX_MSG - 1] = 0; + Trace(msg); + } + + +#else // no YASSL_LOG + + + Log::Log(const char*) {} + Log::~Log() {} + void Log::Trace(const char*) {} + void Log::ShowTCP(socket_t, bool) {} + void Log::ShowData(uint, bool) {} + + +#endif // YASSL_LOG +} // namespace diff --git a/mysql/extra/yassl/src/socket_wrapper.cpp b/mysql/extra/yassl/src/socket_wrapper.cpp new file mode 100644 index 0000000..a23c1c1 --- /dev/null +++ b/mysql/extra/yassl/src/socket_wrapper.cpp @@ -0,0 +1,238 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* The socket wrapper source implements a Socket class that hides the + * differences between Berkely style sockets and Windows sockets, allowing + * transparent TCP access. + */ + + +#include "runtime.hpp" +#include "socket_wrapper.hpp" + +#ifndef _WIN32 + #include + #include + #include + #include + #include + #include + #include + #include +#endif // _WIN32 + +#if defined(__sun) || defined(__SCO_VERSION__) + #include +#endif + +#ifdef _WIN32 + const int SOCKET_EINVAL = WSAEINVAL; + const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK; + const int SOCKET_EAGAIN = WSAEWOULDBLOCK; +#else + const int SOCKET_EINVAL = EINVAL; + const int SOCKET_EWOULDBLOCK = EWOULDBLOCK; + const int SOCKET_EAGAIN = EAGAIN; +#endif // _WIN32 + + +namespace { + + +extern "C" long system_recv(void *ptr, void *buf, size_t count) +{ + yaSSL::socket_t *socket = (yaSSL::socket_t *) ptr; + return ::recv(*socket, reinterpret_cast(buf), count, 0); +} + + +extern "C" long system_send(void *ptr, const void *buf, size_t count) +{ + yaSSL::socket_t *socket = (yaSSL::socket_t *) ptr; + return ::send(*socket, reinterpret_cast(buf), count, 0); +} + + +} + + +namespace yaSSL { + + +Socket::Socket(socket_t s) + : socket_(s), wouldBlock_(false), nonBlocking_(false), + ptr_(&socket_), send_func_(system_send), recv_func_(system_recv) +{} + + +void Socket::set_fd(socket_t s) +{ + socket_ = s; +} + + +socket_t Socket::get_fd() const +{ + return socket_; +} + + +Socket::~Socket() +{ + // don't close automatically now +} + + +void Socket::closeSocket() +{ + if (socket_ != INVALID_SOCKET) { +#ifdef _WIN32 + closesocket(socket_); +#else + close(socket_); +#endif + socket_ = INVALID_SOCKET; + } +} + + +uint Socket::get_ready() const +{ +#ifdef _WIN32 + unsigned long ready = 0; + ioctlsocket(socket_, FIONREAD, &ready); +#else + /* + 64-bit Solaris requires the variable passed to + FIONREAD be a 32-bit value. + */ + unsigned int ready = 0; + ioctl(socket_, FIONREAD, &ready); +#endif + + return ready; +} + + +void Socket::set_transport_ptr(void *ptr) +{ + ptr_ = ptr; +} + + +void Socket::set_transport_recv_function(yaSSL_recv_func_t recv_func) +{ + recv_func_ = recv_func; +} + + +void Socket::set_transport_send_function(yaSSL_send_func_t send_func) +{ + send_func_ = send_func; +} + + +uint Socket::send(const byte* buf, unsigned int sz, unsigned int& written) +{ + const byte* pos = buf; + const byte* end = pos + sz; + + wouldBlock_ = false; + + /* Remove send()/recv() hooks once non-blocking send is implemented. */ + while (pos != end) { + int sent = send_func_(ptr_, pos, static_cast(end - pos)); + if (sent == -1) { + if (get_lastError() == SOCKET_EWOULDBLOCK || + get_lastError() == SOCKET_EAGAIN) { + wouldBlock_ = true; // would have blocked this time only + nonBlocking_ = true; // nonblocking, win32 only way to tell + return 0; + } + return static_cast(-1); + } + pos += sent; + written += sent; + } + + return sz; +} + + +uint Socket::receive(byte* buf, unsigned int sz) +{ + wouldBlock_ = false; + + int recvd = recv_func_(ptr_, buf, sz); + + // idea to seperate error from would block by arnetheduck@gmail.com + if (recvd == -1) { + if (get_lastError() == SOCKET_EWOULDBLOCK || + get_lastError() == SOCKET_EAGAIN) { + wouldBlock_ = true; // would have blocked this time only + nonBlocking_ = true; // socket nonblocking, win32 only way to tell + return 0; + } + } + else if (recvd == 0) + return static_cast(-1); + + return recvd; +} + + +void Socket::shutDown(int how) +{ + shutdown(socket_, how); +} + + +int Socket::get_lastError() +{ +#ifdef _WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +} + + +bool Socket::WouldBlock() const +{ + return wouldBlock_; +} + + +bool Socket::IsNonBlocking() const +{ + return nonBlocking_; +} + + +void Socket::set_lastError(int errorCode) +{ +#ifdef _WIN32 + WSASetLastError(errorCode); +#else + errno = errorCode; +#endif +} + + +} // namespace diff --git a/mysql/extra/yassl/src/ssl.cpp b/mysql/extra/yassl/src/ssl.cpp new file mode 100644 index 0000000..39244a0 --- /dev/null +++ b/mysql/extra/yassl/src/ssl.cpp @@ -0,0 +1,1883 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* SSL source implements all openssl compatibility API functions + * + * TODO: notes are mostly api additions to allow compilation with mysql + * they don't affect normal modes but should be provided for completeness + + * stunnel functions at end of file + */ + + + +/* see man pages for function descriptions */ + +#include "runtime.hpp" +#include "openssl/ssl.h" +#include "handshake.hpp" +#include "yassl_int.hpp" +#include "md5.hpp" // for TaoCrypt MD5 size assert +#include "md4.hpp" // for TaoCrypt MD4 size assert +#include "file.hpp" // for TaoCrypt Source +#include "coding.hpp" // HexDecoder +#include "helpers.hpp" // for placement new hack +#include "rsa.hpp" // for TaoCrypt RSA key decode +#include "dsa.hpp" // for TaoCrypt DSA key decode +#include + +#ifdef _WIN32 + #include // FindFirstFile etc.. +#else + #include // file helper + #include // stat + #include // opendir +#endif + + +namespace yaSSL { + + + +int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) +{ + int ret = SSL_SUCCESS; + + if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) + return SSL_BAD_FILETYPE; + + if (file == NULL || !file[0]) + return SSL_BAD_FILE; + + FILE* input = fopen(file, "rb"); + if (!input) + return SSL_BAD_FILE; + + if (type == CA) { + // may have a bunch of CAs + x509* ptr; + while ( (ptr = PemToDer(input, Cert)) ) + ctx->AddCA(ptr); + + if (!feof(input)) { + fclose(input); + return SSL_BAD_FILE; + } + } + else { + x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_; + + if (format == SSL_FILETYPE_ASN1) { + fseek(input, 0, SEEK_END); + long sz = ftell(input); + rewind(input); + x = NEW_YS x509(sz); // takes ownership + size_t bytes = fread(x->use_buffer(), sz, 1, input); + if (bytes != 1) { + fclose(input); + return SSL_BAD_FILE; + } + } + else { + EncryptedInfo info; + x = PemToDer(input, type, &info); + if (!x) { + fclose(input); + return SSL_BAD_FILE; + } + if (info.set) { + // decrypt + char password[80]; + pem_password_cb cb = ctx->GetPasswordCb(); + if (!cb) { + fclose(input); + return SSL_BAD_FILE; + } + int passwordSz = cb(password, sizeof(password), 0, + ctx->GetUserData()); + byte key[AES_256_KEY_SZ]; // max sizes + byte iv[AES_IV_SZ]; + + // use file's salt for key derivation, but not real iv + TaoCrypt::Source source(info.iv, info.ivSz); + TaoCrypt::HexDecoder dec(source); + memcpy(info.iv, source.get_buffer(), min((uint)sizeof(info.iv), + source.size())); + EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password, + passwordSz, 1, key, iv); + + mySTL::auto_ptr cipher; + if (strncmp(info.name, "DES-CBC", 7) == 0) + cipher.reset(NEW_YS DES); + else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0) + cipher.reset(NEW_YS DES_EDE); + else if (strncmp(info.name, "AES-128-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_128_KEY_SZ)); + else if (strncmp(info.name, "AES-192-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_192_KEY_SZ)); + else if (strncmp(info.name, "AES-256-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_256_KEY_SZ)); + else { + fclose(input); + return SSL_BAD_FILE; + } + cipher->set_decryptKey(key, info.iv); + mySTL::auto_ptr newx(NEW_YS x509(x->get_length())); + cipher->decrypt(newx->use_buffer(), x->get_buffer(), + x->get_length()); + ysDelete(x); + x = newx.release(); + } + } + } + + if (type == PrivateKey && ctx->privateKey_) { + // see if key is valid early + TaoCrypt::Source rsaSource(ctx->privateKey_->get_buffer(), + ctx->privateKey_->get_length()); + TaoCrypt::RSA_PrivateKey rsaKey; + rsaKey.Initialize(rsaSource); + + if (rsaSource.GetError().What()) { + // rsa failed see if DSA works + + TaoCrypt::Source dsaSource(ctx->privateKey_->get_buffer(), + ctx->privateKey_->get_length()); + TaoCrypt::DSA_PrivateKey dsaKey; + dsaKey.Initialize(dsaSource); + + if (dsaSource.GetError().What()) { + // neither worked + ret = SSL_FAILURE; + } + } + } + + fclose(input); + return ret; +} + + +extern "C" { + + +SSL_METHOD* SSLv3_method() +{ + return SSLv3_client_method(); +} + + +SSL_METHOD* SSLv3_server_method() +{ + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,0)); +} + + +SSL_METHOD* SSLv3_client_method() +{ + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,0)); +} + + +SSL_METHOD* TLSv1_server_method() +{ + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1)); +} + + +SSL_METHOD* TLSv1_client_method() +{ + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1)); +} + + +SSL_METHOD* TLSv1_1_server_method() +{ + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2)); +} + + +SSL_METHOD* TLSv1_1_client_method() +{ + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2)); +} + + +SSL_METHOD* SSLv23_server_method() +{ + // compatibility only, no version 2 support, but does SSL 3 and TLS 1 + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2), true); +} + + +SSL_METHOD* SSLv23_client_method() +{ + // compatibility only, no version 2 support, but does SSL 3 and TLS 1 + // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline + // TODO: maybe add support to send SSLv2 hello ??? + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2), true); +} + + +SSL_CTX* SSL_CTX_new(SSL_METHOD* method) +{ + return NEW_YS SSL_CTX(method); +} + + +void SSL_CTX_free(SSL_CTX* ctx) +{ + ysDelete(ctx); +} + + +SSL* SSL_new(SSL_CTX* ctx) +{ + return NEW_YS SSL(ctx); +} + + +void SSL_free(SSL* ssl) +{ + ysDelete(ssl); +} + + +int SSL_set_fd(SSL* ssl, YASSL_SOCKET_T fd) +{ + ssl->useSocket().set_fd(fd); + return SSL_SUCCESS; +} + + +YASSL_SOCKET_T SSL_get_fd(const SSL* ssl) +{ + return ssl->getSocket().get_fd(); +} + + +// if you get an error from connect see note at top of README +int SSL_connect(SSL* ssl) +{ + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl->SetError(no_error); + + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + + ssl->SetError(no_error); + ssl->SendWriteBuffered(); + if (!ssl->GetError()) + ssl->useStates().UseConnect() = + ConnectState(ssl->getStates().GetConnect() + 1); + } + + ClientState neededState; + + switch (ssl->getStates().GetConnect()) { + + case CONNECT_BEGIN : + sendClientHello(*ssl); + if (!ssl->GetError()) + ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; + + case CLIENT_HELLO_SENT : + neededState = ssl->getSecurity().get_resuming() ? + serverFinishedComplete : serverHelloDoneComplete; + while (ssl->getStates().getClient() < neededState) { + if (ssl->GetError()) break; + processReply(*ssl); + // if resumption failed, reset needed state + if (neededState == serverFinishedComplete) + if (!ssl->getSecurity().get_resuming()) + neededState = serverHelloDoneComplete; + } + if (!ssl->GetError()) + ssl->useStates().UseConnect() = FIRST_REPLY_DONE; + + case FIRST_REPLY_DONE : + if(ssl->getCrypto().get_certManager().sendVerify()) + sendCertificate(*ssl); + + if (!ssl->getSecurity().get_resuming()) + sendClientKeyExchange(*ssl); + + if(ssl->getCrypto().get_certManager().sendVerify()) + sendCertificateVerify(*ssl); + + sendChangeCipher(*ssl); + sendFinished(*ssl, client_end); + ssl->flushBuffer(); + + if (!ssl->GetError()) + ssl->useStates().UseConnect() = FINISHED_DONE; + + case FINISHED_DONE : + if (!ssl->getSecurity().get_resuming()) + while (ssl->getStates().getClient() < serverFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } + if (!ssl->GetError()) + ssl->useStates().UseConnect() = SECOND_REPLY_DONE; + + case SECOND_REPLY_DONE : + ssl->verifyState(serverFinishedComplete); + ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); + + if (ssl->GetError()) { + GetErrors().Add(ssl->GetError()); + return SSL_FATAL_ERROR; + } + return SSL_SUCCESS; + + default : + return SSL_FATAL_ERROR; // unkown state + } +} + + +int SSL_write(SSL* ssl, const void* buffer, int sz) +{ + return sendData(*ssl, buffer, sz); +} + + +int SSL_read(SSL* ssl, void* buffer, int sz) +{ + Data data(min(sz, MAX_RECORD_SIZE), static_cast(buffer)); + return receiveData(*ssl, data); +} + + +int SSL_accept(SSL* ssl) +{ + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl->SetError(no_error); + + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + + ssl->SetError(no_error); + ssl->SendWriteBuffered(); + if (!ssl->GetError()) + ssl->useStates().UseAccept() = + AcceptState(ssl->getStates().GetAccept() + 1); + } + + switch (ssl->getStates().GetAccept()) { + + case ACCEPT_BEGIN : + processReply(*ssl); + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; + + case ACCEPT_FIRST_REPLY_DONE : + sendServerHello(*ssl); + + if (!ssl->getSecurity().get_resuming()) { + sendCertificate(*ssl); + + if (ssl->getSecurity().get_connection().send_server_key_) + sendServerKeyExchange(*ssl); + + if(ssl->getCrypto().get_certManager().verifyPeer()) + sendCertificateRequest(*ssl); + + sendServerHelloDone(*ssl); + ssl->flushBuffer(); + } + + if (!ssl->GetError()) + ssl->useStates().UseAccept() = SERVER_HELLO_DONE; + + case SERVER_HELLO_DONE : + if (!ssl->getSecurity().get_resuming()) { + while (ssl->getStates().getServer() < clientFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } + } + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; + + case ACCEPT_SECOND_REPLY_DONE : + sendChangeCipher(*ssl); + sendFinished(*ssl, server_end); + ssl->flushBuffer(); + + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; + + case ACCEPT_FINISHED_DONE : + if (ssl->getSecurity().get_resuming()) { + while (ssl->getStates().getServer() < clientFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } + } + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; + + case ACCEPT_THIRD_REPLY_DONE : + ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); + + if (ssl->GetError()) { + GetErrors().Add(ssl->GetError()); + return SSL_FATAL_ERROR; + } + return SSL_SUCCESS; + + default: + return SSL_FATAL_ERROR; // unknown state + } +} + + +int SSL_do_handshake(SSL* ssl) +{ + if (ssl->getSecurity().get_parms().entity_ == client_end) + return SSL_connect(ssl); + else + return SSL_accept(ssl); +} + + +int SSL_clear(SSL* ssl) +{ + GetErrors().Remove(); + + return SSL_SUCCESS; +} + + +int SSL_shutdown(SSL* ssl) +{ + if (!ssl->GetQuietShutdown()) { + Alert alert(warning, close_notify); + sendAlert(*ssl, alert); + } + ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true); + + GetErrors().Remove(); + + return SSL_SUCCESS; +} + + +void SSL_set_quiet_shutdown(SSL *ssl,int mode) +{ + ssl->SetQuietShutdown(mode != 0); +} + + +int SSL_get_quiet_shutdown(SSL *ssl) +{ + return ssl->GetQuietShutdown(); +} + + +/* on by default but allow user to turn off */ +long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode) +{ + if (mode == SSL_SESS_CACHE_OFF) + ctx->SetSessionCacheOff(); + + if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR) + ctx->SetSessionCacheFlushOff(); + + return SSL_SUCCESS; +} + + +SSL_SESSION* SSL_get_session(SSL* ssl) +{ + if (ssl->getSecurity().GetContext()->GetSessionCacheOff()) + return 0; + + return GetSessions().lookup( + ssl->getSecurity().get_connection().sessionID_); +} + + +int SSL_set_session(SSL* ssl, SSL_SESSION* session) +{ + if (ssl->getSecurity().GetContext()->GetSessionCacheOff()) + return SSL_FAILURE; + + ssl->set_session(session); + return SSL_SUCCESS; +} + + +int SSL_session_reused(SSL* ssl) +{ + return ssl->getSecurity().get_resuming(); +} + + +long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t) +{ + if (!sess) + return SSL_ERROR_NONE; + + sess->SetTimeOut(t); + return SSL_SUCCESS; +} + + +long SSL_get_default_timeout(SSL* /*ssl*/) +{ + return DEFAULT_TIMEOUT; +} + + +void SSL_flush_sessions(SSL_CTX *ctx, long /* tm */) +{ + if (ctx->GetSessionCacheOff()) + return; + + GetSessions().Flush(); +} + + +const char* SSL_get_cipher_name(SSL* ssl) +{ + return SSL_get_cipher(ssl); +} + + +const char* SSL_get_cipher(SSL* ssl) +{ + return ssl->getSecurity().get_parms().cipher_name_; +} + + +// SSLv2 only, not implemented +char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len) +{ + return strncpy(buf, "Not Implemented, SSLv2 only", len); +} + + +const char* SSL_get_cipher_list(SSL* ssl, int priority) +{ + if (priority < 0 || priority >= MAX_CIPHERS) + return 0; + + if (ssl->getSecurity().get_parms().cipher_list_[priority][0]) + return ssl->getSecurity().get_parms().cipher_list_[priority]; + + return 0; +} + + +int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list) +{ + if (ctx->SetCipherList(list)) + return SSL_SUCCESS; + else + return SSL_FAILURE; +} + + +const char* SSL_get_version(SSL* ssl) +{ + static const char* version3 = "SSLv3"; + static const char* version31 = "TLSv1"; + static const char* version32 = "TLSv1.1"; + + if (ssl->isTLSv1_1()) + return version32; + else if(ssl->isTLS()) + return version31; + else + return version3; +} + +const char* SSLeay_version(int) +{ + static const char* version = "SSLeay yaSSL compatibility"; + return version; +} + + +int SSL_get_error(SSL* ssl, int /*previous*/) +{ + return ssl->getStates().What(); +} + + + +/* turn on yaSSL zlib compression + returns 0 for success, else error (not built in) + only need to turn on for client, becuase server on by default if built in + but calling for server will tell you whether it's available or not +*/ +int SSL_set_compression(SSL* ssl) /* Chad didn't rename to ya~ because it is prob. bug. */ +{ + return ssl->SetCompression(); +} + + + +X509* X509_Copy(X509 *x) +{ + if (x == 0) return NULL; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_TIME* before = x->GetBefore(); + ASN1_TIME* after = x->GetAfter(); + + X509 *newX509 = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), + before, after, + issuer->GetCnPosition(), issuer->GetCnLength(), + subject->GetCnPosition(), subject->GetCnLength()); + + return newX509; +} + +X509* SSL_get_peer_certificate(SSL* ssl) +{ + return X509_Copy(ssl->getCrypto().get_certManager().get_peerX509()); +} + + +void X509_free(X509* x) +{ + ysDelete(x); +} + + +X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx) +{ + return ctx->current_cert; +} + + +int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx) +{ + return ctx->error; +} + + +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx) +{ + return ctx->error_depth; +} + +X509* PEM_read_X509(FILE *fp, X509 *x, + pem_password_cb cb, + void *u) +{ + if (fp == NULL) + return NULL; + + // Get x509 handle and encryption information + x509* ptr = PemToDer(fp, Cert); + if (!ptr) + return NULL; + + // Now decode x509 object. + TaoCrypt::SignerList signers; + TaoCrypt::Source source(ptr->get_buffer(), ptr->get_length()); + TaoCrypt::CertDecoder cert(source, true, &signers, true, TaoCrypt::CertDecoder::CA); + + if (cert.GetError().What()) { + ysDelete(ptr); + return NULL; + } + + // Ok. Now create X509 object. + size_t iSz = strlen(cert.GetIssuer()) + 1; + size_t sSz = strlen(cert.GetCommonName()) + 1; + ASN1_STRING beforeDate, afterDate; + beforeDate.data = (unsigned char *) cert.GetBeforeDate(); + beforeDate.type = cert.GetBeforeDateType(); + beforeDate.length = strlen((char *) beforeDate.data) + 1; + afterDate.data = (unsigned char *) cert.GetAfterDate(); + afterDate.type = cert.GetAfterDateType(); + afterDate.length = strlen((char *) afterDate.data) + 1; + + X509 *thisX509 = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), + sSz, &beforeDate, &afterDate, + cert.GetIssuerCnStart(), cert.GetIssuerCnLength(), + cert.GetSubjectCnStart(), cert.GetSubjectCnLength()); + + + ysDelete(ptr); + return thisX509; +} + +// copy name into buffer, at most sz bytes, if buffer is null +// will malloc buffer, caller responsible for freeing +char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz) +{ + if (!name->GetName()) return buffer; + + int len = (int)strlen(name->GetName()) + 1; + int copySz = min(len, sz); + + if (!buffer) { + buffer = (char*)malloc(len); + if (!buffer) return buffer; + copySz = len; + } + + if (copySz == 0) + return buffer; + + memcpy(buffer, name->GetName(), copySz - 1); + buffer[copySz - 1] = 0; + + return buffer; +} + + +X509_NAME* X509_get_issuer_name(X509* x) +{ + return x->GetIssuer(); +} + + +X509_NAME* X509_get_subject_name(X509* x) +{ + return x->GetSubject(); +} + + +void SSL_load_error_strings() // compatibility only +{} + + +void SSL_set_connect_state(SSL*) +{ + // already a client by default +} + + +void SSL_set_accept_state(SSL* ssl) +{ + ssl->useSecurity().use_parms().entity_ = server_end; +} + + +long SSL_get_verify_result(SSL*) +{ + // won't get here if not OK + return X509_V_OK; +} + + +long SSL_CTX_sess_set_cache_size(SSL_CTX* /*ctx*/, long /*sz*/) +{ + // unlimited size, can't set for now + return 0; +} + + +long SSL_CTX_get_session_cache_mode(SSL_CTX*) +{ + // always 0, unlimited size for now + return 0; +} + + +long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh) +{ + if (ctx->SetDH(*dh)) + return SSL_SUCCESS; + else + return SSL_FAILURE; +} + + +int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format) +{ + return read_file(ctx, file, format, Cert); +} + + +int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format) +{ + return read_file(ctx, file, format, PrivateKey); +} + + +void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc) +{ + if (mode & SSL_VERIFY_PEER) + ctx->setVerifyPeer(); + + if (mode == SSL_VERIFY_NONE) + ctx->setVerifyNone(); + + if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ctx->setFailNoCert(); + + ctx->setVerifyCallback(vc); +} + + +int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file, + const char* path) +{ + int ret = SSL_FAILURE; + const int HALF_PATH = 128; + + if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA); + + if (ret == SSL_SUCCESS && path) { + // call read_file for each reqular file in path +#ifdef _WIN32 + + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + + const int DELIMITER_SZ = 2; + const int DELIMITER_STAR_SZ = 3; + int pathSz = (int)strlen(path); + int nameSz = pathSz + DELIMITER_STAR_SZ + 1; // plus 1 for terminator + char* name = NEW_YS char[nameSz]; // directory specification + memset(name, 0, nameSz); + strncpy(name, path, nameSz - DELIMITER_STAR_SZ - 1); + strncat(name, "\\*", DELIMITER_STAR_SZ); + + hFind = FindFirstFile(name, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) { + ysArrayDelete(name); + return SSL_BAD_PATH; + } + + do { + if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + int curSz = (int)strlen(FindFileData.cFileName); + if (pathSz + curSz + DELIMITER_SZ + 1 > nameSz) { + ysArrayDelete(name); + // plus 1 for terminator + nameSz = pathSz + curSz + DELIMITER_SZ + 1; + name = NEW_YS char[nameSz]; + } + memset(name, 0, nameSz); + strncpy(name, path, nameSz - curSz - DELIMITER_SZ - 1); + strncat(name, "\\", DELIMITER_SZ); + strncat(name, FindFileData.cFileName, + nameSz - pathSz - DELIMITER_SZ - 1); + ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA); + } + } while (ret == SSL_SUCCESS && FindNextFile(hFind, &FindFileData)); + + ysArrayDelete(name); + FindClose(hFind); + +#else // _WIN32 + DIR* dir = opendir(path); + if (!dir) return SSL_BAD_PATH; + + struct dirent* entry; + struct stat buf; + const int DELIMITER_SZ = 1; + int pathSz = (int)strlen(path); + int nameSz = pathSz + DELIMITER_SZ + 1; //plus 1 for null terminator + char* name = NEW_YS char[nameSz]; // directory specification + + while (ret == SSL_SUCCESS && (entry = readdir(dir))) { + int curSz = (int)strlen(entry->d_name); + if (pathSz + curSz + DELIMITER_SZ + 1 > nameSz) { + ysArrayDelete(name); + nameSz = pathSz + DELIMITER_SZ + curSz + 1; + name = NEW_YS char[nameSz]; + } + memset(name, 0, nameSz); + strncpy(name, path, nameSz - curSz - 1); + strncat(name, "/", DELIMITER_SZ); + strncat(name, entry->d_name, nameSz - pathSz - DELIMITER_SZ - 1); + + if (stat(name, &buf) < 0) { + ysArrayDelete(name); + closedir(dir); + return SSL_BAD_STAT; + } + + if (S_ISREG(buf.st_mode)) + ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA); + } + + ysArrayDelete(name); + closedir(dir); + +#endif + } + + return ret; +} + + +int SSL_CTX_set_default_verify_paths(SSL_CTX* /*ctx*/) +{ + // TODO: figure out way to set/store default path, then call load_verify + return SSL_NOT_IMPLEMENTED; +} + + +int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*, + unsigned int) +{ + // No application specific context needed for yaSSL + return SSL_SUCCESS; +} + + +int SSL_CTX_check_private_key(SSL_CTX* /*ctx*/) +{ + // TODO: check private against public for RSA match + return SSL_NOT_IMPLEMENTED; +} + + +// TODO: all session stats +long SSL_CTX_sess_accept(SSL_CTX* ctx) +{ + return ctx->GetStats().accept_; +} + + +long SSL_CTX_sess_connect(SSL_CTX* ctx) +{ + return ctx->GetStats().connect_; +} + + +long SSL_CTX_sess_accept_good(SSL_CTX* ctx) +{ + return ctx->GetStats().acceptGood_; +} + + +long SSL_CTX_sess_connect_good(SSL_CTX* ctx) +{ + return ctx->GetStats().connectGood_; +} + + +long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx) +{ + return ctx->GetStats().acceptRenegotiate_; +} + + +long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx) +{ + return ctx->GetStats().connectRenegotiate_; +} + + +long SSL_CTX_sess_hits(SSL_CTX* ctx) +{ + return ctx->GetStats().hits_; +} + + +long SSL_CTX_sess_cb_hits(SSL_CTX* ctx) +{ + return ctx->GetStats().cbHits_; +} + + +long SSL_CTX_sess_cache_full(SSL_CTX* ctx) +{ + return ctx->GetStats().cacheFull_; +} + + +long SSL_CTX_sess_misses(SSL_CTX* ctx) +{ + return ctx->GetStats().misses_; +} + + +long SSL_CTX_sess_timeouts(SSL_CTX* ctx) +{ + return ctx->GetStats().timeouts_; +} + + +long SSL_CTX_sess_number(SSL_CTX* ctx) +{ + return ctx->GetStats().number_; +} + + +long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx) +{ + return ctx->GetStats().getCacheSize_; +} +// end session stats TODO: + + +int SSL_CTX_get_verify_mode(SSL_CTX* ctx) +{ + return ctx->GetStats().verifyMode_; +} + + +int SSL_get_verify_mode(SSL* ssl) +{ + return ssl->getSecurity().GetContext()->GetStats().verifyMode_; +} + + +int SSL_CTX_get_verify_depth(SSL_CTX* ctx) +{ + return ctx->GetStats().verifyDepth_; +} + + +int SSL_get_verify_depth(SSL* ssl) +{ + return ssl->getSecurity().GetContext()->GetStats().verifyDepth_; +} + + +long SSL_CTX_set_options(SSL_CTX* ctx, long options) +{ + ProtocolVersion pv= ctx->getMethod()->getVersion(); + bool multi_proto= ctx->getMethod()->multipleProtocol(); + unsigned long ssl_ctx_mask= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1; + + do + { + if (options == 0) + break; + // only TLSv1.1 + if ((options & ssl_ctx_mask) == ssl_ctx_mask) + { + pv.minor_= 2; + multi_proto= false; + break; + } + // only TLSv1 + ssl_ctx_mask= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1_1; + if((options & ssl_ctx_mask) == ssl_ctx_mask) + { + pv.minor_= 1; + multi_proto= false; + break; + } + // TLSv1.1 and TLSv1 + ssl_ctx_mask= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + if((options & ssl_ctx_mask) == ssl_ctx_mask) + { + pv.minor_= 2; + multi_proto= true; + break; + } + }while(0); + + SSL_METHOD *meth= NEW_YS SSL_METHOD(ctx->getMethod()->getSide(), ProtocolVersion(3,pv.minor_), multi_proto); + ctx->SetMethod(meth); + return SSL_SUCCESS; +} + + +void SSL_CTX_set_info_callback(SSL_CTX*, void (*)()) +{ + // TDOD: +} + + +void OpenSSL_add_all_algorithms() // compatibility only +{} + + +int SSL_library_init() // compatiblity only +{ + return 1; +} + + +DH* DH_new(void) +{ + DH* dh = NEW_YS DH; + if (dh) + dh->p = dh->g = 0; + return dh; +} + + +void DH_free(DH* dh) +{ + ysDelete(dh->g); + ysDelete(dh->p); + ysDelete(dh); +} + + +// convert positive big-endian num of length sz into retVal, which may need to +// be created +BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal) +{ + bool created = false; + mySTL::auto_ptr bn; + + if (!retVal) { + created = true; + bn.reset(NEW_YS BIGNUM); + retVal = bn.get(); + } + + retVal->assign(num, sz); + + if (created) + return bn.release(); + else + return retVal; +} + + +unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *) +{ + //return SSL_NOT_IMPLEMENTED; + return 0; +} + + +void ERR_print_errors_fp(FILE* /*fp*/) +{ + // need ssl access to implement TODO: + //fprintf(fp, "%s", ssl.get_states().errorString_.c_str()); +} + + +char* ERR_error_string(unsigned long errNumber, char* buffer) +{ + static char* msg = (char*)"Please supply a buffer for error string"; + + if (buffer) { + SetErrorString(YasslError(errNumber), buffer); + return buffer; + } + + return msg; +} + + +const char* X509_verify_cert_error_string(long /* error */) +{ + // TODO: + static const char* msg = "Not Implemented"; + return msg; +} + + +const EVP_MD* EVP_md5(void) +{ + static const char* type = "MD5"; + return type; +} + + +const EVP_CIPHER* EVP_des_ede3_cbc(void) +{ + static const char* type = "DES-EDE3-CBC"; + return type; +} + + +int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt, + const byte* data, int sz, int count, byte* key, byte* iv) +{ + // only support MD5 for now + if (strncmp(md, "MD5", 3)) return 0; + + int keyLen = 0; + int ivLen = 0; + + // only support CBC DES and AES for now + if (strncmp(type, "DES-CBC", 7) == 0) { + keyLen = DES_KEY_SZ; + ivLen = DES_IV_SZ; + } + else if (strncmp(type, "DES-EDE3-CBC", 12) == 0) { + keyLen = DES_EDE_KEY_SZ; + ivLen = DES_IV_SZ; + } + else if (strncmp(type, "AES-128-CBC", 11) == 0) { + keyLen = AES_128_KEY_SZ; + ivLen = AES_IV_SZ; + } + else if (strncmp(type, "AES-192-CBC", 11) == 0) { + keyLen = AES_192_KEY_SZ; + ivLen = AES_IV_SZ; + } + else if (strncmp(type, "AES-256-CBC", 11) == 0) { + keyLen = AES_256_KEY_SZ; + ivLen = AES_IV_SZ; + } + else + return 0; + + yaSSL::MD5 myMD; + uint digestSz = myMD.get_digestSize(); + byte digest[SHA_LEN]; // max size + + int keyLeft = keyLen; + int ivLeft = ivLen; + int keyOutput = 0; + + while (keyOutput < (keyLen + ivLen)) { + int digestLeft = digestSz; + // D_(i - 1) + if (keyOutput) // first time D_0 is empty + myMD.update(digest, digestSz); + // data + myMD.update(data, sz); + // salt + if (salt) + myMD.update(salt, EVP_SALT_SZ); + myMD.get_digest(digest); + // count + for (int j = 1; j < count; j++) { + myMD.update(digest, digestSz); + myMD.get_digest(digest); + } + + if (keyLeft) { + int store = min(keyLeft, static_cast(digestSz)); + memcpy(&key[keyLen - keyLeft], digest, store); + + keyOutput += store; + keyLeft -= store; + digestLeft -= store; + } + + if (ivLeft && digestLeft) { + int store = min(ivLeft, digestLeft); + memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store); + + keyOutput += store; + ivLeft -= store; + } + } + return keyOutput; +} + + + +void DES_set_key_unchecked(const_DES_cblock* key, DES_key_schedule* schedule) +{ + memcpy(schedule, key, sizeof(const_DES_cblock)); +} + + +void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz, + DES_key_schedule* ks1, DES_key_schedule* ks2, + DES_key_schedule* ks3, DES_cblock* ivec, int enc) +{ + DES_EDE des; + byte key[DES_EDE_KEY_SZ]; + + memcpy(key, *ks1, DES_BLOCK); + memcpy(&key[DES_BLOCK], *ks2, DES_BLOCK); + memcpy(&key[DES_BLOCK * 2], *ks3, DES_BLOCK); + + if (enc) { + des.set_encryptKey(key, *ivec); + des.encrypt(output, input, sz); + } + else { + des.set_decryptKey(key, *ivec); + des.decrypt(output, input, sz); + } +} + + +// functions for libcurl +int RAND_status() +{ + return 1; /* TaoCrypt provides enough seed */ +} + + +int DES_set_key(const_DES_cblock* key, DES_key_schedule* schedule) +{ + memcpy(schedule, key, sizeof(const_DES_cblock)); + return 1; +} + + +void DES_set_odd_parity(DES_cblock* key) +{ + // not needed now for TaoCrypt +} + + +void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output, + DES_key_schedule* key, int enc) +{ + DES des; + + if (enc) { + des.set_encryptKey(*key, 0); + des.encrypt(*output, *input, DES_BLOCK); + } + else { + des.set_decryptKey(*key, 0); + des.decrypt(*output, *input, DES_BLOCK); + } +} + + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata) +{ + ctx->SetUserData(userdata); +} + + +X509* SSL_get_certificate(SSL* ssl) +{ + return ssl->getCrypto().get_certManager().get_selfX509(); +} + + +EVP_PKEY* SSL_get_privatekey(SSL* ssl) +{ + // only called, not used + return 0; +} + + +void SSL_SESSION_free(SSL_SESSION* session) +{ + // managed by singleton +} + + + +EVP_PKEY* X509_get_pubkey(X509* x) +{ + // called, not used though + return 0; +} + + +int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from) +{ + // called, not used though + return 0; +} + + +void EVP_PKEY_free(EVP_PKEY* pkey) +{ + // never allocated from above +} + + +void ERR_error_string_n(unsigned long e, char *buf, size_t len) +{ + if (len) ERR_error_string(e, buf); +} + + +void ERR_free_strings(void) +{ + // handled internally +} + + +void EVP_cleanup(void) +{ + // nothing to do yet +} + + +ASN1_TIME* X509_get_notBefore(X509* x) +{ + if (x) return x->GetBefore(); + return 0; +} + + +ASN1_TIME* X509_get_notAfter(X509* x) +{ + if (x) return x->GetAfter(); + return 0; +} + + +SSL_METHOD* SSLv2_client_method(void) /* will never work, no v 2 */ +{ + return 0; +} + + +SSL_SESSION* SSL_get1_session(SSL* ssl) /* what's ref count */ +{ + return SSL_get_session(ssl); +} + + +void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x) +{ + // no extension names supported yet +} + + +int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x) +{ + // no extension names supported yet + return 0; +} + + +GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i) +{ + // no extension names supported yet + return 0; +} + + +unsigned char* ASN1_STRING_data(ASN1_STRING* x) +{ + if (x) return x->data; + return 0; +} + + +int ASN1_STRING_length(ASN1_STRING* x) +{ + if (x) return x->length; + return 0; +} + + +int ASN1_STRING_type(ASN1_STRING *x) +{ + if (x) return x->type; + return 0; +} + + +int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos) +{ + int idx = -1; // not found + int cnPos = -1; + + switch (nid) { + case NID_commonName: + cnPos = name->GetCnPosition(); + if (lastpos < cnPos) + idx = cnPos; + break; + } + + return idx; +} + + +ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne) +{ + // the same in yaSSL + return ne; +} + + +X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc) +{ + return name->GetEntry(loc); +} + + +// already formatted, caller responsible for freeing *out +int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in) +{ + if (!in) return 0; + + *out = (unsigned char*)malloc(in->length + 1); + if (*out) { + memcpy(*out, in->data, in->length); + (*out)[in->length] = 0; + } + return in->length; +} + + +void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx) +{ + // no extensions supported yet + return 0; +} + + +void MD4_Init(MD4_CTX* md4) +{ + // make sure we have a big enough buffer + typedef char ok[sizeof(md4->buffer) >= sizeof(TaoCrypt::MD4) ? 1 : -1]; + (void) sizeof(ok); + + // using TaoCrypt since no dynamic memory allocated + // and no destructor will be called + new (reinterpret_cast(md4->buffer)) TaoCrypt::MD4(); +} + + +void MD4_Update(MD4_CTX* md4, const void* data, unsigned long sz) +{ + reinterpret_cast(md4->buffer)->Update( + static_cast(data), static_cast(sz)); +} + + +void MD4_Final(unsigned char* hash, MD4_CTX* md4) +{ + reinterpret_cast(md4->buffer)->Final(hash); +} + + +void MD5_Init(MD5_CTX* md5) +{ + // make sure we have a big enough buffer + typedef char ok[sizeof(md5->buffer) >= sizeof(TaoCrypt::MD5) ? 1 : -1]; + (void) sizeof(ok); + + // using TaoCrypt since no dynamic memory allocated + // and no destructor will be called + new (reinterpret_cast(md5->buffer)) TaoCrypt::MD5(); +} + + +void MD5_Update(MD5_CTX* md5, const void* data, unsigned long sz) +{ + reinterpret_cast(md5->buffer)->Update( + static_cast(data), static_cast(sz)); +} + + +void MD5_Final(unsigned char* hash, MD5_CTX* md5) +{ + reinterpret_cast(md5->buffer)->Final(hash); +} + + +int RAND_bytes(unsigned char* buf, int num) +{ + RandomPool ran; + + if (ran.GetError()) return 0; + + ran.Fill(buf, num); + return 1; +} + + +int SSL_peek(SSL* ssl, void* buffer, int sz) +{ + Data data(min(sz, MAX_RECORD_SIZE), static_cast(buffer)); + return receiveData(*ssl, data, true); +} + + +int SSL_pending(SSL* ssl) +{ + // Just in case there's pending data that hasn't been processed yet... + char c; + SSL_peek(ssl, &c, 1); + + return ssl->bufferedData(); +} + + +void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb) +{ + ctx->SetPasswordCb(cb); +} + + +int SSLeay_add_ssl_algorithms() // compatibility only +{ + return 1; +} + + +void ERR_remove_state(unsigned long) +{ + GetErrors().Remove(); +} + + +int ERR_GET_REASON(int l) +{ + return l & 0xfff; +} + + +unsigned long err_helper(bool peek = false) +{ + int ysError = GetErrors().Lookup(peek); + + // translate cert error for libcurl, it uses OpenSSL hex code + switch (ysError) { + case TaoCrypt::SIG_OTHER_E: + return CERTFICATE_ERROR; + break; + default : + return 0; + } + + return 0; // shut up compiler +} + + +unsigned long ERR_peek_error() +{ + return err_helper(true); +} + + +unsigned long ERR_get_error() +{ + return err_helper(); +} + + + // functions for stunnel + + void RAND_screen() + { + // TODO: + } + + + const char* RAND_file_name(char*, size_t) + { + // TODO: + return 0; + } + + + int RAND_write_file(const char*) + { + // TODO: + return 0; + } + + + int RAND_load_file(const char*, long) + { + // TODO: + return 0; + } + + + void RSA_free(RSA*) + { + // TODO: + } + + + RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*) + { + // TODO: + return 0; + } + + + int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long) + { + // TODO: + return SSL_SUCCESS; + } + + + int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long) + { + // TODO: + return SSL_SUCCESS; + } + + + X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void) + { + // TODO: + return 0; + } + + + X509_LOOKUP_METHOD* X509_LOOKUP_file(void) + { + // TODO: + return 0; + } + + + X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*) + { + // TODO: + return 0; + } + + + int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, X509_OBJECT*) + { + // TODO: + return SSL_SUCCESS; + } + + + X509_STORE* X509_STORE_new(void) + { + // TODO: + return 0; + } + + char* SSL_alert_type_string_long(int) + { + // TODO: + return 0; + } + + + char* SSL_alert_desc_string_long(int) + { + // TODO: + return 0; + } + + + char* SSL_state_string_long(SSL*) + { + // TODO: + return 0; + } + + + void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int)) + { + // TDOD: + } + + + long SSL_CTX_set_timeout(SSL_CTX*, long) + { + // TDOD: + return SSL_SUCCESS; + } + + + int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*) + { + // TDOD: + return SSL_SUCCESS; + } + + + int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int) + { + // TDOD: + return SSL_SUCCESS; + } + + + int SSL_set_rfd(SSL*, int) + { + return SSL_SUCCESS; // TODO: + } + + + int SSL_set_wfd(SSL*, int) + { + return SSL_SUCCESS; // TODO: + } + + + int SSL_want_read(SSL*) + { + return 0; // TODO: + } + + + int SSL_want_write(SSL*) + { + return 0; // TODO: + } + + + void SSL_set_shutdown(SSL*, int) + { + // TODO: + } + + + SSL_CIPHER* SSL_get_current_cipher(SSL*) + { + // TODO: + return 0; + } + + + char* SSL_CIPHER_description(SSL_CIPHER*, char*, int) + { + // TODO: + return 0; + } + + + + // end stunnel needs + + char *yaSSL_ASN1_TIME_to_string(ASN1_TIME *time, char *buf, size_t len) + { + tm t; + static const char *month_names[12]= + { + "Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec" + }; + + TaoCrypt::ASN1_TIME_extract(time->data, time->type, &t); +#ifdef _WIN32 + _snprintf(buf, len, "%s %2d %02d:%02d:%02d %d GMT", +#else + snprintf(buf, len, "%s %2d %02d:%02d:%02d %d GMT", +#endif + month_names[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min, + t.tm_sec, t.tm_year + 1900); + return buf; + } + + + void yaSSL_transport_set_ptr(SSL *ssl, void *ptr) + { + ssl->useSocket().set_transport_ptr(ptr); + } + + + void yaSSL_transport_set_recv_function(SSL *ssl, yaSSL_recv_func_t func) + { + ssl->useSocket().set_transport_recv_function(func); + } + + + void yaSSL_transport_set_send_function(SSL *ssl, yaSSL_send_func_t func) + { + ssl->useSocket().set_transport_send_function(func); + } + +} // extern "C" +} // namespace diff --git a/mysql/extra/yassl/src/timer.cpp b/mysql/extra/yassl/src/timer.cpp new file mode 100644 index 0000000..a1b9063 --- /dev/null +++ b/mysql/extra/yassl/src/timer.cpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* timer.cpp implements a high res and low res timer + * +*/ + +#include "runtime.hpp" +#include "timer.hpp" + +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace yaSSL { + +#ifdef _WIN32 + + timer_d timer() + { + static bool init(false); + static LARGE_INTEGER freq; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = true; + } + + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + + return static_cast(count.QuadPart) / freq.QuadPart; + } + + + uint lowResTimer() + { + return static_cast(timer()); + } + +#else // _WIN32 + + timer_d timer() + { + struct timeval tv; + gettimeofday(&tv, 0); + + return static_cast(tv.tv_sec) + + static_cast(tv.tv_usec) / 1000000; + } + + + uint lowResTimer() + { + struct timeval tv; + gettimeofday(&tv, 0); + + return tv.tv_sec; + } + + +#endif // _WIN32 +} // namespace yaSSL diff --git a/mysql/extra/yassl/src/yassl_error.cpp b/mysql/extra/yassl/src/yassl_error.cpp new file mode 100644 index 0000000..5169b7d --- /dev/null +++ b/mysql/extra/yassl/src/yassl_error.cpp @@ -0,0 +1,288 @@ +/* + Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* yaSSL error implements and an exception class + */ + +#include "runtime.hpp" +#include "yassl_error.hpp" +#include "error.hpp" // TaoCrypt error numbers +#include "openssl/ssl.h" // SSL_ERROR_WANT_READ +#include // strncpy + +#ifdef _MSC_VER + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable: 4996) +#endif + +namespace yaSSL { + + +/* may bring back in future +Error::Error(const char* s, YasslError e, Library l) + : mySTL::runtime_error(s), error_(e), lib_(l) +{ +} + + +YasslError Error::get_number() const +{ + return error_; +} + + +Library Error::get_lib() const +{ + + return lib_; +} +*/ + + +void SetErrorString(YasslError error, char* buffer) +{ + using namespace TaoCrypt; + const int max = MAX_ERROR_SZ; // shorthand + int localError = error; // errors from a few enums + + switch (localError) { + + // yaSSL proper errors + case range_error : + strncpy(buffer, "buffer index error, out of range", max); + break; + + case realloc_error : + strncpy(buffer, "trying to realloc a fixed buffer", max); + break; + + case factory_error : + strncpy(buffer, "unknown factory create request", max); + break; + + case unknown_cipher : + strncpy(buffer, "trying to use an unknown cipher", max); + break; + + case prefix_error : + strncpy(buffer, "bad master secret derivation, prefix too big", max); + break; + + case record_layer : + strncpy(buffer, "record layer not ready yet", max); + break; + + case handshake_layer : + strncpy(buffer, "handshake layer not ready yet", max); + break; + + case out_of_order : + strncpy(buffer, "handshake message received in wrong order", max); + break; + + case bad_input : + strncpy(buffer, "bad cipher suite input", max); + break; + + case match_error : + strncpy(buffer, "unable to match a supported cipher suite", max); + break; + + case no_key_file : + strncpy(buffer, "the server needs a private key file", max); + break; + + case verify_error : + strncpy(buffer, "unable to verify peer checksum", max); + break; + + case send_error : + strncpy(buffer, "socket layer send error", max); + break; + + case receive_error : + strncpy(buffer, "socket layer receive error", max); + break; + + case certificate_error : + strncpy(buffer, "unable to proccess cerificate", max); + break; + + case privateKey_error : + strncpy(buffer, "unable to proccess private key, bad format", max); + break; + + case badVersion_error : + strncpy(buffer, "protocol version mismatch", max); + break; + + case compress_error : + strncpy(buffer, "compression error", max); + break; + + case decompress_error : + strncpy(buffer, "decompression error", max); + break; + + case pms_version_error : + strncpy(buffer, "bad PreMasterSecret version error", max); + break; + + case sanityCipher_error : + strncpy(buffer, "sanity check on cipher text size error", max); + break; + + case rsaSignFault_error: + strncpy(buffer, "rsa signature fault error", max); + break; + + // openssl errors + case SSL_ERROR_WANT_READ : + strncpy(buffer, "the read operation would block", max); + break; + + case SSL_ERROR_WANT_WRITE : + strncpy(buffer, "the write operation would block", max); + break; + + case CERTFICATE_ERROR : + strncpy(buffer, "Unable to verify certificate", max); + break; + + // TaoCrypt errors + case NO_ERROR_E : + strncpy(buffer, "not in error state", max); + break; + + case WINCRYPT_E : + strncpy(buffer, "bad wincrypt acquire", max); + break; + + case CRYPTGEN_E : + strncpy(buffer, "CryptGenRandom error", max); + break; + + case OPEN_RAN_E : + strncpy(buffer, "unable to use random device", max); + break; + + case READ_RAN_E : + strncpy(buffer, "unable to use random device", max); + break; + + case INTEGER_E : + strncpy(buffer, "ASN: bad DER Integer Header", max); + break; + + case SEQUENCE_E : + strncpy(buffer, "ASN: bad Sequence Header", max); + break; + + case SET_E : + strncpy(buffer, "ASN: bad Set Header", max); + break; + + case VERSION_E : + strncpy(buffer, "ASN: version length not 1", max); + break; + + case SIG_OID_E : + strncpy(buffer, "ASN: signature OID mismatch", max); + break; + + case BIT_STR_E : + strncpy(buffer, "ASN: bad BitString Header", max); + break; + + case UNKNOWN_OID_E : + strncpy(buffer, "ASN: unknown key OID type", max); + break; + + case OBJECT_ID_E : + strncpy(buffer, "ASN: bad Ojbect ID Header", max); + break; + + case TAG_NULL_E : + strncpy(buffer, "ASN: expected TAG NULL", max); + break; + + case EXPECT_0_E : + strncpy(buffer, "ASN: expected 0", max); + break; + + case OCTET_STR_E : + strncpy(buffer, "ASN: bad Octet String Header", max); + break; + + case TIME_E : + strncpy(buffer, "ASN: bad TIME", max); + break; + + case DATE_SZ_E : + strncpy(buffer, "ASN: bad Date Size", max); + break; + + case SIG_LEN_E : + strncpy(buffer, "ASN: bad Signature Length", max); + break; + + case UNKOWN_SIG_E : + strncpy(buffer, "ASN: unknown signature OID", max); + break; + + case UNKOWN_HASH_E : + strncpy(buffer, "ASN: unknown hash OID", max); + break; + + case DSA_SZ_E : + strncpy(buffer, "ASN: bad DSA r or s size", max); + break; + + case BEFORE_DATE_E : + strncpy(buffer, "ASN: before date in the future", max); + break; + + case AFTER_DATE_E : + strncpy(buffer, "ASN: after date in the past", max); + break; + + case SIG_CONFIRM_E : + strncpy(buffer, "ASN: bad self signature confirmation", max); + break; + + case SIG_OTHER_E : + strncpy(buffer, "ASN: bad other signature confirmation", max); + break; + + case CONTENT_E : + strncpy(buffer, "bad content processing", max); + break; + + case PEM_E : + strncpy(buffer, "bad PEM format processing", max); + break; + + default : + strncpy(buffer, "unknown error number", max); + } +} + + + +} // namespace yaSSL diff --git a/mysql/extra/yassl/src/yassl_imp.cpp b/mysql/extra/yassl/src/yassl_imp.cpp new file mode 100644 index 0000000..ea09777 --- /dev/null +++ b/mysql/extra/yassl/src/yassl_imp.cpp @@ -0,0 +1,2642 @@ +/* + Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* yaSSL source implements all SSL.v3 secification structures. + */ + +#include "runtime.hpp" +#include "yassl_int.hpp" +#include "handshake.hpp" + +#include "asn.hpp" // provide crypto wrapper?? + + + +namespace yaSSL { + + +namespace { // locals + +bool isTLS(ProtocolVersion pv) +{ + if (pv.major_ >= 3 && pv.minor_ >= 1) + return true; + + return false; +} + + +} // namespace (locals) + + +void hashHandShake(SSL&, const input_buffer&, uint); + + +ProtocolVersion::ProtocolVersion(uint8 maj, uint8 min) + : major_(maj), minor_(min) +{} + + +// construct key exchange with known ssl parms +void ClientKeyExchange::createKey(SSL& ssl) +{ + const ClientKeyFactory& ckf = ssl.getFactory().getClientKey(); + client_key_ = ckf.CreateObject(ssl.getSecurity().get_parms().kea_); + + if (!client_key_) + ssl.SetError(factory_error); +} + + +// construct key exchange with known ssl parms +void ServerKeyExchange::createKey(SSL& ssl) +{ + const ServerKeyFactory& skf = ssl.getFactory().getServerKey(); + server_key_ = skf.CreateObject(ssl.getSecurity().get_parms().kea_); + + if (!server_key_) + ssl.SetError(factory_error); +} + + +// build/set PreMaster secret and encrypt, client side +void EncryptedPreMasterSecret::build(SSL& ssl) +{ + opaque tmp[SECRET_LEN]; + memset(tmp, 0, sizeof(tmp)); + ssl.getCrypto().get_random().Fill(tmp, SECRET_LEN); + ProtocolVersion pv = ssl.getSecurity().get_connection().chVersion_; + tmp[0] = pv.major_; + tmp[1] = pv.minor_; + ssl.set_preMaster(tmp, SECRET_LEN); + + const CertManager& cert = ssl.getCrypto().get_certManager(); + RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength()); + bool tls = ssl.isTLS(); // if TLS, put length for encrypted data + alloc(rsa.get_cipherLength() + (tls ? 2 : 0)); + byte* holder = secret_; + if (tls) { + byte len[2]; + c16toa(rsa.get_cipherLength(), len); + memcpy(secret_, len, sizeof(len)); + holder += 2; + } + rsa.encrypt(holder, tmp, SECRET_LEN, ssl.getCrypto().get_random()); +} + + +// build/set premaster and Client Public key, client side +void ClientDiffieHellmanPublic::build(SSL& ssl) +{ + DiffieHellman& dhServer = ssl.useCrypto().use_dh(); + DiffieHellman dhClient(dhServer); + + uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same + + alloc(keyLength, true); + dhClient.makeAgreement(dhServer.get_publicKey(), + dhServer.get_publicKeyLength()); + c16toa(keyLength, Yc_); + memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength); + + ssl.set_preMaster(dhClient.get_agreedKey(), keyLength); +} + + +// build server exhange, server side +void DH_Server::build(SSL& ssl) +{ + DiffieHellman& dhServer = ssl.useCrypto().use_dh(); + + int pSz, gSz, pubSz; + dhServer.set_sizes(pSz, gSz, pubSz); + dhServer.get_parms(parms_.alloc_p(pSz), parms_.alloc_g(gSz), + parms_.alloc_pub(pubSz)); + + short sigSz = 0; + mySTL::auto_ptr auth; + const CertManager& cert = ssl.getCrypto().get_certManager(); + + if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { + if (cert.get_keyType() != rsa_sa_algo) { + ssl.SetError(privateKey_error); + return; + } + auth.reset(NEW_YS RSA(cert.get_privateKey(), + cert.get_privateKeyLength(), false)); + } + else { + if (cert.get_keyType() != dsa_sa_algo) { + ssl.SetError(privateKey_error); + return; + } + auth.reset(NEW_YS DSS(cert.get_privateKey(), + cert.get_privateKeyLength(), false)); + sigSz += DSS_ENCODED_EXTRA; + } + + sigSz += auth->get_signatureLength(); + if (!sigSz) { + ssl.SetError(privateKey_error); + return; + } + + length_ = 8; // pLen + gLen + YsLen + SigLen + length_ += pSz + gSz + pubSz + sigSz; + + output_buffer tmp(length_); + byte len[2]; + // P + c16toa(pSz, len); + tmp.write(len, sizeof(len)); + tmp.write(parms_.get_p(), pSz); + // G + c16toa(gSz, len); + tmp.write(len, sizeof(len)); + tmp.write(parms_.get_g(), gSz); + // Ys + c16toa(pubSz, len); + tmp.write(len, sizeof(len)); + tmp.write(parms_.get_pub(), pubSz); + + // Sig + byte hash[FINISHED_SZ]; + MD5 md5; + SHA sha; + signature_ = NEW_YS byte[sigSz]; + + const Connection& conn = ssl.getSecurity().get_connection(); + // md5 + md5.update(conn.client_random_, RAN_LEN); + md5.update(conn.server_random_, RAN_LEN); + md5.update(tmp.get_buffer(), tmp.get_size()); + md5.get_digest(hash); + + // sha + sha.update(conn.client_random_, RAN_LEN); + sha.update(conn.server_random_, RAN_LEN); + sha.update(tmp.get_buffer(), tmp.get_size()); + sha.get_digest(&hash[MD5_LEN]); + + if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { + auth->sign(signature_, hash, sizeof(hash), + ssl.getCrypto().get_random()); + // check for rsa signautre fault + if (!auth->verify(hash, sizeof(hash), signature_, + auth->get_signatureLength())) { + ssl.SetError(rsaSignFault_error); + return; + } + } + else { + auth->sign(signature_, &hash[MD5_LEN], SHA_LEN, + ssl.getCrypto().get_random()); + byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA]; + TaoCrypt::EncodeDSA_Signature(signature_, encoded); + memcpy(signature_, encoded, sizeof(encoded)); + } + + c16toa(sigSz, len); + tmp.write(len, sizeof(len)); + tmp.write(signature_, sigSz); + + // key message + keyMessage_ = NEW_YS opaque[length_]; + memcpy(keyMessage_, tmp.get_buffer(), tmp.get_size()); +} + + +// read PreMaster secret and decrypt, server side +void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + const CertManager& cert = ssl.getCrypto().get_certManager(); + RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false); + uint16 cipherLen = rsa.get_cipherLength(); + if (ssl.isTLS()) { + byte len[2]; + len[0] = input[AUTO]; + len[1] = input[AUTO]; + ato16(len, cipherLen); + } + alloc(cipherLen); + input.read(secret_, length_); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + opaque preMasterSecret[SECRET_LEN]; + memset(preMasterSecret, 0, sizeof(preMasterSecret)); + rsa.decrypt(preMasterSecret, secret_, length_, + ssl.getCrypto().get_random()); + + ProtocolVersion pv = ssl.getSecurity().get_connection().chVersion_; + if (pv.major_ != preMasterSecret[0] || pv.minor_ != preMasterSecret[1]) + ssl.SetError(pms_version_error); // continue deriving for timing attack + + ssl.set_preMaster(preMasterSecret, SECRET_LEN); + ssl.makeMasterSecret(); +} + + +EncryptedPreMasterSecret::EncryptedPreMasterSecret() + : secret_(0), length_(0) +{} + + +EncryptedPreMasterSecret::~EncryptedPreMasterSecret() +{ + ysArrayDelete(secret_); +} + + +int EncryptedPreMasterSecret::get_length() const +{ + return length_; +} + + +opaque* EncryptedPreMasterSecret::get_clientKey() const +{ + return secret_; +} + + +void EncryptedPreMasterSecret::alloc(int sz) +{ + length_ = sz; + secret_ = NEW_YS opaque[sz]; +} + + +// read client's public key, server side +void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input) +{ + if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { + ssl.SetError(bad_input); + return; + } + + DiffieHellman& dh = ssl.useCrypto().use_dh(); + + uint16 keyLength; + byte tmp[2]; + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, keyLength); + + if (keyLength < dh.get_agreedKeyLength()/2) { + ssl.SetError(bad_input); + return; + } + + alloc(keyLength); + input.read(Yc_, keyLength); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + dh.makeAgreement(Yc_, keyLength); + + ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength()); + ssl.makeMasterSecret(); +} + + +ClientDiffieHellmanPublic::ClientDiffieHellmanPublic() + : length_(0), Yc_(0) +{} + + +ClientDiffieHellmanPublic::~ClientDiffieHellmanPublic() +{ + ysArrayDelete(Yc_); +} + + +int ClientDiffieHellmanPublic::get_length() const +{ + return length_; +} + + +opaque* ClientDiffieHellmanPublic::get_clientKey() const +{ + return Yc_; +} + + +void ClientDiffieHellmanPublic::alloc(int sz, bool offset) +{ + length_ = sz + (offset ? KEY_OFFSET : 0); + Yc_ = NEW_YS opaque[length_]; +} + + +// read server's p, g, public key and sig, client side +void DH_Server::read(SSL& ssl, input_buffer& input) +{ + if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { + ssl.SetError(bad_input); + return; + } + uint16 length, messageTotal = 6; // pSz + gSz + pubSz + byte tmp[2]; + + // p + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, length); + messageTotal += length; + + input.read(parms_.alloc_p(length), length); + if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { + ssl.SetError(bad_input); + return; + } + + // g + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, length); + messageTotal += length; + + input.read(parms_.alloc_g(length), length); + if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { + ssl.SetError(bad_input); + return; + } + + // pub + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, length); + messageTotal += length; + + input.read(parms_.alloc_pub(length), length); + if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { + ssl.SetError(bad_input); + return; + } + + // save message for hash verify + input_buffer message(messageTotal); + input.set_current(input.get_current() - messageTotal); + input.read(message.get_buffer(), messageTotal); + message.add_size(messageTotal); + if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { + ssl.SetError(bad_input); + return; + } + + // signature + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, length); + + if (length == 0) { + ssl.SetError(bad_input); + return; + } + signature_ = NEW_YS byte[length]; + input.read(signature_, length); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + // verify signature + byte hash[FINISHED_SZ]; + MD5 md5; + SHA sha; + + const Connection& conn = ssl.getSecurity().get_connection(); + // md5 + md5.update(conn.client_random_, RAN_LEN); + md5.update(conn.server_random_, RAN_LEN); + md5.update(message.get_buffer(), message.get_size()); + md5.get_digest(hash); + + // sha + sha.update(conn.client_random_, RAN_LEN); + sha.update(conn.server_random_, RAN_LEN); + sha.update(message.get_buffer(), message.get_size()); + sha.get_digest(&hash[MD5_LEN]); + + const CertManager& cert = ssl.getCrypto().get_certManager(); + + if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { + RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength()); + if (!rsa.verify(hash, sizeof(hash), signature_, length)) + ssl.SetError(verify_error); + } + else { + byte decodedSig[DSS_SIG_SZ]; + length = TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, length); + + DSS dss(cert.get_peerKey(), cert.get_peerKeyLength()); + if (!dss.verify(&hash[MD5_LEN], SHA_LEN, decodedSig, length)) + ssl.SetError(verify_error); + } + + // save input + ssl.useCrypto().SetDH(NEW_YS DiffieHellman(parms_.get_p(), + parms_.get_pSize(), parms_.get_g(), parms_.get_gSize(), + parms_.get_pub(), parms_.get_pubSize(), + ssl.getCrypto().get_random())); +} + + +DH_Server::DH_Server() + : signature_(0), length_(0), keyMessage_(0) +{} + + +DH_Server::~DH_Server() +{ + ysArrayDelete(keyMessage_); + ysArrayDelete(signature_); +} + + +int DH_Server::get_length() const +{ + return length_; +} + + +opaque* DH_Server::get_serverKey() const +{ + return keyMessage_; +} + + +// set available suites +Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, + ProtocolVersion pv, bool haveDH) : entity_(ce) +{ + pending_ = true; // suite not set yet + strncpy(cipher_name_, "NONE", 5); + + removeDH_ = !haveDH; // only use on server side for set suites + + if (ciphers.setSuites_) { // use user set list + suites_size_ = ciphers.suiteSz_; + memcpy(suites_, ciphers.suites_, ciphers.suiteSz_); + SetCipherNames(); + } + else + SetSuites(pv, ce == server_end && removeDH_); // defaults + +} + + +void Parameters::SetSuites(ProtocolVersion pv, bool removeDH, bool removeRSA, + bool removeDSA) +{ + int i = 0; + // available suites, best first + // when adding more, make sure cipher_names is updated and + // MAX_CIPHERS is big enough + + if (isTLS(pv)) { + if (!removeDH) { + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; + } + if (!removeDSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA; + } + } + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA; + } + if (!removeDH) { + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; + } + if (!removeDSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_SHA; + } + } + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA; + suites_[i++] = 0x00; + suites_[i++] = TLS_RSA_WITH_AES_256_CBC_RMD160; + suites_[i++] = 0x00; + suites_[i++] = TLS_RSA_WITH_AES_128_CBC_RMD160; + suites_[i++] = 0x00; + suites_[i++] = TLS_RSA_WITH_3DES_EDE_CBC_RMD160; + } + if (!removeDH) { + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_RMD160; + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_RMD160; + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160; + } + if (!removeDSA) { + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_RMD160; + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_RMD160; + suites_[i++] = 0x00; + suites_[i++] = TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160; + } + } + } + + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = SSL_RSA_WITH_RC4_128_SHA; + suites_[i++] = 0x00; + suites_[i++] = SSL_RSA_WITH_RC4_128_MD5; + + suites_[i++] = 0x00; + suites_[i++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA; + suites_[i++] = 0x00; + suites_[i++] = SSL_RSA_WITH_DES_CBC_SHA; + } + if (!removeDH) { + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA; + } + if (!removeDSA) { + suites_[i++] = 0x00; + suites_[i++] = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA; + } + if (!removeRSA) { + suites_[i++] = 0x00; + suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA; + } + if (!removeDSA) { + suites_[i++] = 0x00; + suites_[i++] = SSL_DHE_DSS_WITH_DES_CBC_SHA; + } + } + + suites_size_ = i; + + SetCipherNames(); +} + + +void Parameters::SetCipherNames() +{ + const int suites = suites_size_ / 2; + int pos = 0; + + for (int j = 0; j < suites; j++) { + int index = suites_[j*2 + 1]; // every other suite is suite id + size_t len = strlen(cipher_names[index]) + 1; + strncpy(cipher_list_[pos++], cipher_names[index], len); + } + cipher_list_[pos][0] = 0; +} + + +// input operator for RecordLayerHeader, adjust stream +input_buffer& operator>>(input_buffer& input, RecordLayerHeader& hdr) +{ + hdr.type_ = ContentType(input[AUTO]); + hdr.version_.major_ = input[AUTO]; + hdr.version_.minor_ = input[AUTO]; + + // length + byte tmp[2]; + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, hdr.length_); + + return input; +} + + +// output operator for RecordLayerHeader +output_buffer& operator<<(output_buffer& output, const RecordLayerHeader& hdr) +{ + output[AUTO] = hdr.type_; + output[AUTO] = hdr.version_.major_; + output[AUTO] = hdr.version_.minor_; + + // length + byte tmp[2]; + c16toa(hdr.length_, tmp); + output[AUTO] = tmp[0]; + output[AUTO] = tmp[1]; + + return output; +} + + +// virtual input operator for Messages +input_buffer& operator>>(input_buffer& input, Message& msg) +{ + return msg.set(input); +} + +// virtual output operator for Messages +output_buffer& operator<<(output_buffer& output, const Message& msg) +{ + return msg.get(output); +} + + +// input operator for HandShakeHeader +input_buffer& operator>>(input_buffer& input, HandShakeHeader& hs) +{ + hs.type_ = HandShakeType(input[AUTO]); + + hs.length_[0] = input[AUTO]; + hs.length_[1] = input[AUTO]; + hs.length_[2] = input[AUTO]; + + return input; +} + + +// output operator for HandShakeHeader +output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr) +{ + output[AUTO] = hdr.type_; + output.write(hdr.length_, sizeof(hdr.length_)); + return output; +} + + +// HandShake Header Processing function +void HandShakeHeader::Process(input_buffer& input, SSL& ssl) +{ + ssl.verifyState(*this); + if (ssl.GetError()) return; + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + const HandShakeFactory& hsf = ssl.getFactory().getHandShake(); + mySTL::auto_ptr hs(hsf.CreateObject(type_)); + if (!hs.get()) { + ssl.SetError(factory_error); + return; + } + + uint len = c24to32(length_); + if (len > input.get_remaining()) { + ssl.SetError(bad_input); + return; + } + hashHandShake(ssl, input, len); + + hs->set_length(len); + input >> *hs; + hs->Process(input, ssl); +} + + +ContentType HandShakeHeader::get_type() const +{ + return handshake; +} + + +uint16 HandShakeHeader::get_length() const +{ + return c24to32(length_); +} + + +HandShakeType HandShakeHeader::get_handshakeType() const +{ + return type_; +} + + +void HandShakeHeader::set_type(HandShakeType hst) +{ + type_ = hst; +} + + +void HandShakeHeader::set_length(uint32 u32) +{ + c32to24(u32, length_); +} + + +input_buffer& HandShakeHeader::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& HandShakeHeader::get(output_buffer& out) const +{ + return out << *this; +} + + + +int HandShakeBase::get_length() const +{ + return length_; +} + + +void HandShakeBase::set_length(int l) +{ + length_ = l; +} + + +// for building buffer's type field +HandShakeType HandShakeBase::get_type() const +{ + return no_shake; +} + + +input_buffer& HandShakeBase::set(input_buffer& in) +{ + return in; +} + + +output_buffer& HandShakeBase::get(output_buffer& out) const +{ + return out; +} + + +void HandShakeBase::Process(input_buffer&, SSL&) +{} + + +input_buffer& HelloRequest::set(input_buffer& in) +{ + return in; +} + + +output_buffer& HelloRequest::get(output_buffer& out) const +{ + return out; +} + + +void HelloRequest::Process(input_buffer&, SSL&) +{} + + +HandShakeType HelloRequest::get_type() const +{ + return hello_request; +} + + +// input operator for CipherSpec +input_buffer& operator>>(input_buffer& input, ChangeCipherSpec& cs) +{ + cs.type_ = CipherChoice(input[AUTO]); + return input; +} + +// output operator for CipherSpec +output_buffer& operator<<(output_buffer& output, const ChangeCipherSpec& cs) +{ + output[AUTO] = cs.type_; + return output; +} + + +ChangeCipherSpec::ChangeCipherSpec() + : type_(change_cipher_spec_choice) +{} + + +input_buffer& ChangeCipherSpec::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& ChangeCipherSpec::get(output_buffer& out) const +{ + return out << *this; +} + + +ContentType ChangeCipherSpec::get_type() const +{ + return change_cipher_spec; +} + + +uint16 ChangeCipherSpec::get_length() const +{ + return SIZEOF_ENUM; +} + + +// CipherSpec processing handler +void ChangeCipherSpec::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + // detect duplicate change_cipher + if (ssl.getSecurity().get_parms().pending_ == false) { + ssl.order_error(); + return; + } + + ssl.useSecurity().use_parms().pending_ = false; + if (ssl.getSecurity().get_resuming()) { + if (ssl.getSecurity().get_parms().entity_ == client_end) + buildFinished(ssl, ssl.useHashes().use_verify(), server); // server + } + else if (ssl.getSecurity().get_parms().entity_ == server_end) + buildFinished(ssl, ssl.useHashes().use_verify(), client); // client +} + + +Alert::Alert(AlertLevel al, AlertDescription ad) + : level_(al), description_(ad) +{} + + +ContentType Alert::get_type() const +{ + return alert; +} + + +uint16 Alert::get_length() const +{ + return SIZEOF_ENUM * 2; +} + + +input_buffer& Alert::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& Alert::get(output_buffer& out) const +{ + return out << *this; +} + + +// input operator for Alert +input_buffer& operator>>(input_buffer& input, Alert& a) +{ + a.level_ = AlertLevel(input[AUTO]); + a.description_ = AlertDescription(input[AUTO]); + + return input; +} + + +// output operator for Alert +output_buffer& operator<<(output_buffer& output, const Alert& a) +{ + output[AUTO] = a.level_; + output[AUTO] = a.description_; + return output; +} + + +// Alert processing handler +void Alert::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + if (ssl.getSecurity().get_parms().pending_ == false) { // encrypted alert + int aSz = get_length(); // alert size already read on input + opaque verify[SHA_LEN]; + const opaque* data = input.get_buffer() + input.get_current() - aSz; + + if (ssl.isTLS()) + TLS_hmac(ssl, verify, data, aSz, alert, true); + else + hmac(ssl, verify, data, aSz, alert, true); + + // read mac and skip fill + int digestSz = ssl.getCrypto().get_digest().get_digestSize(); + opaque mac[SHA_LEN]; + input.read(mac, digestSz); + + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + int ivExtra = 0; + opaque fill; + + if (ssl.isTLSv1_1()) + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + int padSz = ssl.getSecurity().get_parms().encrypt_size_ - ivExtra - + aSz - digestSz; + for (int i = 0; i < padSz; i++) + fill = input[AUTO]; + } + + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + // verify + if (memcmp(mac, verify, digestSz)) { + ssl.SetError(verify_error); + return; + } + } + if (level_ == fatal) { + ssl.useStates().useRecord() = recordNotReady; + ssl.useStates().useHandShake() = handShakeNotReady; + ssl.SetError(YasslError(description_)); + } +} + + +Data::Data() + : length_(0), buffer_(0), write_buffer_(0) +{} + + +Data::Data(uint16 len, opaque* b) + : length_(len), buffer_(b), write_buffer_(0) +{} + + +void Data::SetData(uint16 len, const opaque* buffer) +{ + length_ = len; + write_buffer_ = buffer; +} + +input_buffer& Data::set(input_buffer& in) +{ + return in; +} + + +output_buffer& Data::get(output_buffer& out) const +{ + return out << *this; +} + + +ContentType Data::get_type() const +{ + return application_data; +} + + +uint16 Data::get_length() const +{ + return length_; +} + + +void Data::set_length(uint16 l) +{ + length_ = l; +} + + +opaque* Data::set_buffer() +{ + return buffer_; +} + + +// output operator for Data +output_buffer& operator<<(output_buffer& output, const Data& data) +{ + output.write(data.write_buffer_, data.length_); + return output; +} + + +// check all bytes for equality +static int constant_compare(const byte* a, const byte* b, int len) +{ + int good = 0; + int bad = 0; + + for (int i = 0; i < len; i++) { + if (a[i] == b[i]) + good++; + else + bad++; + } + + if (good == len) + return 0; + else + return 0 - bad; // failure +} + + +// check bytes for pad value +static int pad_check(const byte* input, byte pad, int len) +{ + int good = 0; + int bad = 0; + + for (int i = 0; i < len; i++) { + if (input[i] == pad) + good++; + else + bad++; + } + + if (good == len) + return 0; + else + return 0 - bad; // failure +} + + +// get number of compression rounds +static inline int get_rounds(int pLen, int padLen, int t) +{ + int roundL1 = 1; // round ups + int roundL2 = 1; + + int L1 = COMPRESS_CONSTANT + pLen - t; + int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t; + + L1 -= COMPRESS_UPPER; + L2 -= COMPRESS_UPPER; + + if ( (L1 % COMPRESS_LOWER) == 0) + roundL1 = 0; + if ( (L2 % COMPRESS_LOWER) == 0) + roundL2 = 0; + + L1 /= COMPRESS_LOWER; + L2 /= COMPRESS_LOWER; + + L1 += roundL1; + L2 += roundL2; + + return L1 - L2; +} + + +// do compression rounds on dummy data +static inline void compress_rounds(SSL& ssl, int rounds, const byte* dummy) +{ + if (rounds) { + Digest* digest = NULL; + + MACAlgorithm ma = ssl.getSecurity().get_parms().mac_algorithm_; + if (ma == sha) + digest = NEW_YS SHA; + else if (ma == md5) + digest = NEW_YS MD5; + else if (ma == rmd) + digest = NEW_YS RMD; + else + return; + + for (int i = 0; i < rounds; i++) + digest->update(dummy, COMPRESS_LOWER); + + ysDelete(digest); + } +} + + +// timing resistant pad verification +static int timing_verify(SSL& ssl, const byte* input, int padLen, int t, + int pLen) +{ + byte verify[SHA_LEN]; + byte dummy[MAX_PAD_SIZE]; + + memset(dummy, 1, sizeof(dummy)); + + if ( (t + padLen + 1) > pLen) { + pad_check(dummy, (byte)padLen, MAX_PAD_SIZE); + if (ssl.isTLS()) + TLS_hmac(ssl, verify, input, pLen - t, application_data, 1); + else + hmac(ssl, verify, input, pLen - t, application_data, 1); + constant_compare(verify, input + pLen - t, t); + + return -1; + } + + if (pad_check(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) { + pad_check(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); + if (ssl.isTLS()) + TLS_hmac(ssl, verify, input, pLen - t, application_data, 1); + else + hmac(ssl, verify, input, pLen - t, application_data, 1); + constant_compare(verify, input + pLen - t, t); + + return -1; + } + + pad_check(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); + if (ssl.isTLS()) + TLS_hmac(ssl, verify, input, pLen - padLen - 1 - t, application_data,1); + else + hmac(ssl, verify, input, pLen - padLen - 1 - t, application_data, 1); + + compress_rounds(ssl, get_rounds(pLen, padLen, t), dummy); + + if (constant_compare(verify, input + (pLen - padLen - 1 - t), t) != 0) + return -1; + + return 0; +} + + +// Process handler for Data +void Data::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + int msgSz = ssl.getSecurity().get_parms().encrypt_size_; + int pad = 0, padSz = 0; + int ivExtra = 0; + int digestSz = ssl.getCrypto().get_digest().get_digestSize(); + const byte* rawData = input.get_buffer() + input.get_current(); + opaque verify[SHA_LEN]; + + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + if (ssl.isTLSv1_1()) // IV + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + pad = *(input.get_buffer() + input.get_current() + msgSz -ivExtra - 1); + padSz = 1; + + if (ssl.isTLS()) { + if (timing_verify(ssl, rawData, pad,digestSz, msgSz-ivExtra) != 0) { + ssl.SetError(verify_error); + return; + } + } + else { // SSLv3, some don't do this padding right + int sz3 = msgSz - digestSz - pad - 1; + hmac(ssl, verify, rawData, sz3, application_data, true); + if (constant_compare(verify, rawData + sz3, digestSz) != 0) { + ssl.SetError(verify_error); + return; + } + } + } + else { // stream + int streamSz = msgSz - digestSz; + if (ssl.isTLS()) + TLS_hmac(ssl, verify, rawData, streamSz, application_data, true); + else + hmac(ssl, verify, rawData, streamSz, application_data, true); + if (constant_compare(verify, rawData + streamSz, digestSz) != 0) { + ssl.SetError(verify_error); + return; + } + } + + int dataSz = msgSz - ivExtra - digestSz - pad - padSz; + + if (dataSz < 0 || dataSz > (MAX_RECORD_SIZE + COMPRESS_EXTRA)) { + ssl.SetError(bad_input); + return; + } + + // read data + if (dataSz) { // could be compressed + if (ssl.CompressionOn()) { + input_buffer tmp; + if (DeCompress(input, dataSz, tmp) == -1) { + ssl.SetError(decompress_error); + return; + } + ssl.addData(NEW_YS input_buffer(tmp.get_size(), + tmp.get_buffer(), tmp.get_size())); + } + else { + input_buffer* data; + ssl.addData(data = NEW_YS input_buffer(dataSz)); + input.read(data->get_buffer(), dataSz); + data->add_size(dataSz); + } + } + + // advance past mac and fill + input.set_current(input.get_current() + digestSz + pad + padSz); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } +} + + +// virtual input operator for HandShakes +input_buffer& operator>>(input_buffer& input, HandShakeBase& hs) +{ + return hs.set(input); +} + + +// virtual output operator for HandShakes +output_buffer& operator<<(output_buffer& output, const HandShakeBase& hs) +{ + return hs.get(output); +} + + +Certificate::Certificate(const x509* cert) : cert_(cert) +{ + if (cert) + set_length(cert_->get_length() + 2 * CERT_HEADER); // list and cert size + else + set_length(CERT_HEADER); // total blank cert size, just list header +} + + +const opaque* Certificate::get_buffer() const +{ + if (cert_) + return cert_->get_buffer(); + + return NULL; +} + + +// output operator for Certificate +output_buffer& operator<<(output_buffer& output, const Certificate& cert) +{ + uint sz = cert.get_length(); + opaque tmp[CERT_HEADER]; + + if ((int)sz > CERT_HEADER) + sz -= 2 * CERT_HEADER; // actual cert, not including headers + else { + sz = 0; // blank cert case + c32to24(sz, tmp); + output.write(tmp, CERT_HEADER); + + return output; + } + + c32to24(sz + CERT_HEADER, tmp); + output.write(tmp, CERT_HEADER); + c32to24(sz, tmp); + output.write(tmp, CERT_HEADER); + output.write(cert.get_buffer(), sz); + + return output; +} + + +// certificate processing handler +void Certificate::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + CertManager& cm = ssl.useCrypto().use_certManager(); + + uint32 list_sz; + byte tmp[3]; + + if (input.get_remaining() < sizeof(tmp)) { + ssl.SetError(YasslError(bad_input)); + return; + } + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + tmp[2] = input[AUTO]; + c24to32(tmp, list_sz); + + if (list_sz > (uint)MAX_RECORD_SIZE) { // sanity check + ssl.SetError(YasslError(bad_input)); + return; + } + + while (list_sz) { + // cert size + uint32 cert_sz; + + if (input.get_remaining() < sizeof(tmp)) { + ssl.SetError(YasslError(bad_input)); + return; + } + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + tmp[2] = input[AUTO]; + c24to32(tmp, cert_sz); + + if (cert_sz > (uint)MAX_RECORD_SIZE || input.get_remaining() < cert_sz){ + ssl.SetError(YasslError(bad_input)); + return; + } + if (cert_sz) { + x509* myCert; + cm.AddPeerCert(myCert = NEW_YS x509(cert_sz)); + input.read(myCert->use_buffer(), myCert->get_length()); + } + + list_sz -= cert_sz + CERT_HEADER; + } + if (int err = cm.Validate()) + ssl.SetError(YasslError(err)); + else if (ssl.getSecurity().get_parms().entity_ == client_end) + ssl.useStates().useClient() = serverCertComplete; +} + + +Certificate::Certificate() + : cert_(0) +{} + + +input_buffer& Certificate::set(input_buffer& in) +{ + return in; +} + + +output_buffer& Certificate::get(output_buffer& out) const +{ + return out << *this; +} + + +HandShakeType Certificate::get_type() const +{ + return certificate; +} + + +ServerDHParams::ServerDHParams() + : pSz_(0), gSz_(0), pubSz_(0), p_(0), g_(0), Ys_(0) +{} + + +ServerDHParams::~ServerDHParams() +{ + ysArrayDelete(Ys_); + ysArrayDelete(g_); + ysArrayDelete(p_); +} + + +int ServerDHParams::get_pSize() const +{ + return pSz_; +} + + +int ServerDHParams::get_gSize() const +{ + return gSz_; +} + + +int ServerDHParams::get_pubSize() const +{ + return pubSz_; +} + + +const opaque* ServerDHParams::get_p() const +{ + return p_; +} + + +const opaque* ServerDHParams::get_g() const +{ + return g_; +} + + +const opaque* ServerDHParams::get_pub() const +{ + return Ys_; +} + + +opaque* ServerDHParams::alloc_p(int sz) +{ + p_ = NEW_YS opaque[pSz_ = sz]; + return p_; +} + + +opaque* ServerDHParams::alloc_g(int sz) +{ + g_ = NEW_YS opaque[gSz_ = sz]; + return g_; +} + + +opaque* ServerDHParams::alloc_pub(int sz) +{ + Ys_ = NEW_YS opaque[pubSz_ = sz]; + return Ys_; +} + + +int ServerKeyBase::get_length() const +{ + return 0; +} + + +opaque* ServerKeyBase::get_serverKey() const +{ + return 0; +} + + +// input operator for ServerHello +input_buffer& operator>>(input_buffer& input, ServerHello& hello) +{ + // Protocol + hello.server_version_.major_ = input[AUTO]; + hello.server_version_.minor_ = input[AUTO]; + + // Random + input.read(hello.random_, RAN_LEN); + + // Session + hello.id_len_ = input[AUTO]; + if (hello.id_len_ > ID_LEN) { + input.set_error(); + return input; + } + if (hello.id_len_) + input.read(hello.session_id_, hello.id_len_); + + // Suites + hello.cipher_suite_[0] = input[AUTO]; + hello.cipher_suite_[1] = input[AUTO]; + + // Compression + hello.compression_method_ = CompressionMethod(input[AUTO]); + + return input; +} + + +// output operator for ServerHello +output_buffer& operator<<(output_buffer& output, const ServerHello& hello) +{ + // Protocol + output[AUTO] = hello.server_version_.major_; + output[AUTO] = hello.server_version_.minor_; + + // Random + output.write(hello.random_, RAN_LEN); + + // Session + output[AUTO] = hello.id_len_; + output.write(hello.session_id_, ID_LEN); + + // Suites + output[AUTO] = hello.cipher_suite_[0]; + output[AUTO] = hello.cipher_suite_[1]; + + // Compression + output[AUTO] = hello.compression_method_; + + return output; +} + + +// Server Hello processing handler +void ServerHello::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + if (ssl.GetMultiProtocol()) { // SSLv23 support + if (ssl.isTLS() && server_version_.minor_ < 1) + // downgrade to SSLv3 + ssl.useSecurity().use_connection().TurnOffTLS(); + else if (ssl.isTLSv1_1() && server_version_.minor_ == 1) + // downdrage to TLSv1 + ssl.useSecurity().use_connection().TurnOffTLS1_1(); + } + else if (ssl.isTLSv1_1() && server_version_.minor_ < 2) { + ssl.SetError(badVersion_error); + return; + } + else if (ssl.isTLS() && server_version_.minor_ < 1) { + ssl.SetError(badVersion_error); + return; + } + else if (!ssl.isTLS() && (server_version_.major_ == 3 && + server_version_.minor_ >= 1)) { + ssl.SetError(badVersion_error); + return; + } + if (cipher_suite_[0] != 0x00) { + ssl.SetError(unknown_cipher); + return; + } + ssl.set_pending(cipher_suite_[1]); + ssl.set_random(random_, server_end); + if (id_len_) + ssl.set_sessionID(session_id_); + else + ssl.useSecurity().use_connection().sessionID_Set_ = false; + + if (ssl.getSecurity().get_resuming()) { + if (memcmp(session_id_, ssl.getSecurity().get_resume().GetID(), + ID_LEN) == 0) { + ssl.set_masterSecret(ssl.getSecurity().get_resume().GetSecret()); + if (ssl.isTLS()) + ssl.deriveTLSKeys(); + else + ssl.deriveKeys(); + ssl.useStates().useClient() = serverHelloDoneComplete; + return; + } + else { + ssl.useSecurity().set_resuming(false); + ssl.useLog().Trace("server denied resumption"); + } + } + + if (ssl.CompressionOn() && !compression_method_) + ssl.UnSetCompression(); // server isn't supporting yaSSL zlib request + + ssl.useStates().useClient() = serverHelloComplete; +} + + +ServerHello::ServerHello() +{ + memset(random_, 0, RAN_LEN); + memset(session_id_, 0, ID_LEN); +} + + +ServerHello::ServerHello(ProtocolVersion pv, bool useCompression) + : server_version_(pv), + compression_method_(useCompression ? zlib : no_compression) +{ + memset(random_, 0, RAN_LEN); + memset(session_id_, 0, ID_LEN); +} + + +input_buffer& ServerHello::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& ServerHello::get(output_buffer& out) const +{ + return out << *this; +} + + +HandShakeType ServerHello::get_type() const +{ + return server_hello; +} + + +const opaque* ServerHello::get_random() const +{ + return random_; +} + + +// Server Hello Done processing handler +void ServerHelloDone::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + ssl.useStates().useClient() = serverHelloDoneComplete; +} + + +ServerHelloDone::ServerHelloDone() +{ + set_length(0); +} + + +input_buffer& ServerHelloDone::set(input_buffer& in) +{ + return in; +} + + +output_buffer& ServerHelloDone::get(output_buffer& out) const +{ + return out; +} + + +HandShakeType ServerHelloDone::get_type() const +{ + return server_hello_done; +} + + +int ClientKeyBase::get_length() const +{ + return 0; +} + + +opaque* ClientKeyBase::get_clientKey() const +{ + return 0; +} + + +// input operator for Client Hello +input_buffer& operator>>(input_buffer& input, ClientHello& hello) +{ + uint begin = input.get_current(); // could have extensions at end + + // Protocol + hello.client_version_.major_ = input[AUTO]; + hello.client_version_.minor_ = input[AUTO]; + + // Random + input.read(hello.random_, RAN_LEN); + + // Session + hello.id_len_ = input[AUTO]; + if (hello.id_len_) input.read(hello.session_id_, ID_LEN); + + // Suites + byte tmp[2]; + uint16 len; + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, len); + + hello.suite_len_ = min(len, static_cast(MAX_SUITE_SZ)); + input.read(hello.cipher_suites_, hello.suite_len_); + if (len > hello.suite_len_) // ignore extra suites + input.set_current(input.get_current() + len - hello.suite_len_); + + // Compression + hello.comp_len_ = input[AUTO]; + hello.compression_methods_ = no_compression; + while (hello.comp_len_--) { + CompressionMethod cm = CompressionMethod(input[AUTO]); + if (cm == zlib) + hello.compression_methods_ = zlib; + } + + uint read = input.get_current() - begin; + uint expected = hello.get_length(); + + // ignore client hello extensions for now + if (read < expected) + input.set_current(input.get_current() + expected - read); + + return input; +} + + +// output operaotr for Client Hello +output_buffer& operator<<(output_buffer& output, const ClientHello& hello) +{ + // Protocol + output[AUTO] = hello.client_version_.major_; + output[AUTO] = hello.client_version_.minor_; + + // Random + output.write(hello.random_, RAN_LEN); + + // Session + output[AUTO] = hello.id_len_; + if (hello.id_len_) output.write(hello.session_id_, ID_LEN); + + // Suites + byte tmp[2]; + c16toa(hello.suite_len_, tmp); + output[AUTO] = tmp[0]; + output[AUTO] = tmp[1]; + output.write(hello.cipher_suites_, hello.suite_len_); + + // Compression + output[AUTO] = hello.comp_len_; + output[AUTO] = hello.compression_methods_; + + return output; +} + + +// Client Hello processing handler +void ClientHello::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + // store version for pre master secret + ssl.useSecurity().use_connection().chVersion_ = client_version_; + + if (client_version_.major_ != 3) { + ssl.SetError(badVersion_error); + return; + } + if (ssl.GetMultiProtocol()) { // SSLv23 support + if (ssl.isTLS() && client_version_.minor_ < 1) { + // downgrade to SSLv3 + ssl.useSecurity().use_connection().TurnOffTLS(); + + ProtocolVersion pv = ssl.getSecurity().get_connection().version_; + bool removeDH = ssl.getSecurity().get_parms().removeDH_; + bool removeRSA = false; + bool removeDSA = false; + + const CertManager& cm = ssl.getCrypto().get_certManager(); + if (cm.get_keyType() == rsa_sa_algo) + removeDSA = true; + else + removeRSA = true; + + // reset w/ SSL suites + ssl.useSecurity().use_parms().SetSuites(pv, removeDH, removeRSA, + removeDSA); + } + else if (ssl.isTLSv1_1() && client_version_.minor_ == 1) + // downgrade to TLSv1, but use same suites + ssl.useSecurity().use_connection().TurnOffTLS1_1(); + } + else if (ssl.isTLSv1_1() && client_version_.minor_ < 2) { + ssl.SetError(badVersion_error); + return; + } + else if (ssl.isTLS() && client_version_.minor_ < 1) { + ssl.SetError(badVersion_error); + return; + } + else if (!ssl.isTLS() && client_version_.minor_ >= 1) { + ssl.SetError(badVersion_error); + return; + } + + ssl.set_random(random_, client_end); + + while (id_len_) { // trying to resume + SSL_SESSION* session = 0; + if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) + session = GetSessions().lookup(session_id_); + if (!session) { + ssl.useLog().Trace("session lookup failed"); + break; + } + ssl.set_session(session); + ssl.useSecurity().set_resuming(true); + ssl.matchSuite(session->GetSuite(), SUITE_LEN); + if (ssl.GetError()) return; + ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); + ssl.set_masterSecret(session->GetSecret()); + + opaque serverRandom[RAN_LEN]; + ssl.getCrypto().get_random().Fill(serverRandom, sizeof(serverRandom)); + ssl.set_random(serverRandom, server_end); + if (ssl.isTLS()) + ssl.deriveTLSKeys(); + else + ssl.deriveKeys(); + ssl.useStates().useServer() = clientKeyExchangeComplete; + return; + } + ssl.matchSuite(cipher_suites_, suite_len_); + if (ssl.GetError()) return; + ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); + + if (compression_methods_ == zlib) + ssl.SetCompression(); + + ssl.useStates().useServer() = clientHelloComplete; +} + + +input_buffer& ClientHello::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& ClientHello::get(output_buffer& out) const +{ + return out << *this; +} + + +HandShakeType ClientHello::get_type() const +{ + return client_hello; +} + + +const opaque* ClientHello::get_random() const +{ + return random_; +} + + +ClientHello::ClientHello() +{ + memset(random_, 0, RAN_LEN); +} + + +ClientHello::ClientHello(ProtocolVersion pv, bool useCompression) + : client_version_(pv), + compression_methods_(useCompression ? zlib : no_compression) +{ + memset(random_, 0, RAN_LEN); +} + + +// output operator for ServerKeyExchange +output_buffer& operator<<(output_buffer& output, const ServerKeyExchange& sk) +{ + output.write(sk.getKey(), sk.getKeyLength()); + return output; +} + + +// Server Key Exchange processing handler +void ServerKeyExchange::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + createKey(ssl); + if (ssl.GetError()) return; + server_key_->read(ssl, input); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + ssl.useStates().useClient() = serverKeyExchangeComplete; +} + + +ServerKeyExchange::ServerKeyExchange(SSL& ssl) +{ + createKey(ssl); +} + + +ServerKeyExchange::ServerKeyExchange() + : server_key_(0) +{} + + +ServerKeyExchange::~ServerKeyExchange() +{ + ysDelete(server_key_); +} + + +void ServerKeyExchange::build(SSL& ssl) +{ + server_key_->build(ssl); + set_length(server_key_->get_length()); +} + + +const opaque* ServerKeyExchange::getKey() const +{ + return server_key_->get_serverKey(); +} + + +int ServerKeyExchange::getKeyLength() const +{ + return server_key_->get_length(); +} + + +input_buffer& ServerKeyExchange::set(input_buffer& in) +{ + return in; // process does +} + + +output_buffer& ServerKeyExchange::get(output_buffer& out) const +{ + return out << *this; +} + + +HandShakeType ServerKeyExchange::get_type() const +{ + return server_key_exchange; +} + + +// CertificateRequest +CertificateRequest::CertificateRequest() + : typeTotal_(0) +{ + memset(certificate_types_, 0, sizeof(certificate_types_)); +} + + +CertificateRequest::~CertificateRequest() +{ + + STL::for_each(certificate_authorities_.begin(), + certificate_authorities_.end(), + del_ptr_zero()) ; +} + + +void CertificateRequest::Build() +{ + certificate_types_[0] = rsa_sign; + certificate_types_[1] = dss_sign; + + typeTotal_ = 2; + + uint16 authCount = 0; + uint16 authSz = 0; + + for (int j = 0; j < authCount; j++) { + int sz = REQUEST_HEADER + MIN_DIS_SIZE; + DistinguishedName dn; + certificate_authorities_.push_back(dn = NEW_YS byte[sz]); + + opaque tmp[REQUEST_HEADER]; + c16toa(MIN_DIS_SIZE, tmp); + memcpy(dn, tmp, sizeof(tmp)); + + // fill w/ junk for now + memcpy(dn, tmp, MIN_DIS_SIZE); + authSz += sz; + } + + set_length(SIZEOF_ENUM + typeTotal_ + REQUEST_HEADER + authSz); +} + + +input_buffer& CertificateRequest::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& CertificateRequest::get(output_buffer& out) const +{ + return out << *this; +} + + +// input operator for CertificateRequest +input_buffer& operator>>(input_buffer& input, CertificateRequest& request) +{ + // types + request.typeTotal_ = input[AUTO]; + if (request.typeTotal_ > CERT_TYPES) { + input.set_error(); + return input; + } + for (int i = 0; i < request.typeTotal_; i++) + request.certificate_types_[i] = ClientCertificateType(input[AUTO]); + + byte tmp[2]; + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + uint16 sz; + ato16(tmp, sz); + + // authorities + while (sz) { + uint16 dnSz; + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + ato16(tmp, dnSz); + + input.set_current(input.get_current() + dnSz); + + sz -= dnSz + REQUEST_HEADER; + + if (input.get_error()) + break; + } + + return input; +} + + +// output operator for CertificateRequest +output_buffer& operator<<(output_buffer& output, + const CertificateRequest& request) +{ + // types + output[AUTO] = request.typeTotal_; + for (int i = 0; i < request.typeTotal_; i++) + output[AUTO] = request.certificate_types_[i]; + + // authorities + opaque tmp[REQUEST_HEADER]; + c16toa(request.get_length() - SIZEOF_ENUM - + request.typeTotal_ - REQUEST_HEADER, tmp); + output.write(tmp, sizeof(tmp)); + + STL::list::const_iterator first = + request.certificate_authorities_.begin(); + STL::list::const_iterator last = + request.certificate_authorities_.end(); + while (first != last) { + uint16 sz; + ato16(*first, sz); + output.write(*first, sz + REQUEST_HEADER); + + ++first; + } + + return output; +} + + +// CertificateRequest processing handler +void CertificateRequest::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + CertManager& cm = ssl.useCrypto().use_certManager(); + + cm.setSendVerify(); + if (cm.get_cert() == NULL || cm.get_privateKey() == NULL) + cm.setSendBlankCert(); // send blank cert, OpenSSL requires now +} + + +HandShakeType CertificateRequest::get_type() const +{ + return certificate_request; +} + + +// CertificateVerify +CertificateVerify::CertificateVerify() : signature_(0) +{} + + +CertificateVerify::~CertificateVerify() +{ + ysArrayDelete(signature_); +} + + +void CertificateVerify::Build(SSL& ssl) +{ + build_certHashes(ssl, hashes_); + + uint16 sz = 0; + byte len[VERIFY_HEADER]; + mySTL::auto_array sig; + + // sign + const CertManager& cert = ssl.getCrypto().get_certManager(); + if (cert.get_keyType() == rsa_sa_algo) { + RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false); + + sz = rsa.get_cipherLength() + VERIFY_HEADER; + sig.reset(NEW_YS byte[sz]); + + c16toa(sz - VERIFY_HEADER, len); + memcpy(sig.get(), len, VERIFY_HEADER); + rsa.sign(sig.get() + VERIFY_HEADER, hashes_.md5_, sizeof(Hashes), + ssl.getCrypto().get_random()); + // check for rsa signautre fault + if (!rsa.verify(hashes_.md5_, sizeof(Hashes), sig.get() + VERIFY_HEADER, + rsa.get_cipherLength())) { + ssl.SetError(rsaSignFault_error); + return; + } + } + else { // DSA + DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false); + + sz = DSS_SIG_SZ + DSS_ENCODED_EXTRA + VERIFY_HEADER; + sig.reset(NEW_YS byte[sz]); + + c16toa(sz - VERIFY_HEADER, len); + memcpy(sig.get(), len, VERIFY_HEADER); + dss.sign(sig.get() + VERIFY_HEADER, hashes_.sha_, SHA_LEN, + ssl.getCrypto().get_random()); + + byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA]; + TaoCrypt::EncodeDSA_Signature(sig.get() + VERIFY_HEADER, encoded); + memcpy(sig.get() + VERIFY_HEADER, encoded, sizeof(encoded)); + } + set_length(sz); + signature_ = sig.release(); +} + + +input_buffer& CertificateVerify::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& CertificateVerify::get(output_buffer& out) const +{ + return out << *this; +} + + +// input operator for CertificateVerify +input_buffer& operator>>(input_buffer& input, CertificateVerify& request) +{ + byte tmp[VERIFY_HEADER]; + tmp[0] = input[AUTO]; + tmp[1] = input[AUTO]; + + uint16 sz = 0; + ato16(tmp, sz); + request.set_length(sz); + + if (sz == 0) { + input.set_error(); + return input; + } + + request.signature_ = NEW_YS byte[sz]; + input.read(request.signature_, sz); + + return input; +} + + +// output operator for CertificateVerify +output_buffer& operator<<(output_buffer& output, + const CertificateVerify& verify) +{ + output.write(verify.signature_, verify.get_length()); + + return output; +} + + +// CertificateVerify processing handler +void CertificateVerify::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + const Hashes& hashVerify = ssl.getHashes().get_certVerify(); + const CertManager& cert = ssl.getCrypto().get_certManager(); + + if (cert.get_peerKeyType() == rsa_sa_algo) { + RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength()); + + if (!rsa.verify(hashVerify.md5_, sizeof(hashVerify), signature_, + get_length())) + ssl.SetError(verify_error); + } + else { // DSA + byte decodedSig[DSS_SIG_SZ]; + TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, get_length()); + + DSS dss(cert.get_peerKey(), cert.get_peerKeyLength()); + if (!dss.verify(hashVerify.sha_, SHA_LEN, decodedSig, get_length())) + ssl.SetError(verify_error); + } +} + + +HandShakeType CertificateVerify::get_type() const +{ + return certificate_verify; +} + + +// output operator for ClientKeyExchange +output_buffer& operator<<(output_buffer& output, const ClientKeyExchange& ck) +{ + output.write(ck.getKey(), ck.getKeyLength()); + return output; +} + + +// Client Key Exchange processing handler +void ClientKeyExchange::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + createKey(ssl); + if (ssl.GetError()) return; + client_key_->read(ssl, input); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + if (ssl.getCrypto().get_certManager().verifyPeer()) + build_certHashes(ssl, ssl.useHashes().use_certVerify()); + + ssl.useStates().useServer() = clientKeyExchangeComplete; +} + + +ClientKeyExchange::ClientKeyExchange(SSL& ssl) +{ + createKey(ssl); +} + + +ClientKeyExchange::ClientKeyExchange() + : client_key_(0) +{} + + +ClientKeyExchange::~ClientKeyExchange() +{ + ysDelete(client_key_); +} + + +void ClientKeyExchange::build(SSL& ssl) +{ + client_key_->build(ssl); + set_length(client_key_->get_length()); +} + +const opaque* ClientKeyExchange::getKey() const +{ + return client_key_->get_clientKey(); +} + + +int ClientKeyExchange::getKeyLength() const +{ + return client_key_->get_length(); +} + + +input_buffer& ClientKeyExchange::set(input_buffer& in) +{ + return in; +} + + +output_buffer& ClientKeyExchange::get(output_buffer& out) const +{ + return out << *this; +} + + +HandShakeType ClientKeyExchange::get_type() const +{ + return client_key_exchange; +} + + +// input operator for Finished +input_buffer& operator>>(input_buffer& input, Finished&) +{ + /* do in process */ + + return input; +} + +// output operator for Finished +output_buffer& operator<<(output_buffer& output, const Finished& fin) +{ + if (fin.get_length() == FINISHED_SZ) { + output.write(fin.hashes_.md5_, MD5_LEN); + output.write(fin.hashes_.sha_, SHA_LEN); + } + else // TLS_FINISHED_SZ + output.write(fin.hashes_.md5_, TLS_FINISHED_SZ); + + return output; +} + + +// Finished processing handler +void Finished::Process(input_buffer& input, SSL& ssl) +{ + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + // verify hashes + const Finished& verify = ssl.getHashes().get_verify(); + uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ; + + input.read(hashes_.md5_, finishedSz); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + if (memcmp(&hashes_, &verify.hashes_, finishedSz)) { + ssl.SetError(verify_error); + return; + } + + // read verify mac + opaque verifyMAC[SHA_LEN]; + uint macSz = finishedSz + HANDSHAKE_HEADER; + + if (ssl.isTLS()) + TLS_hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() + - macSz, macSz, handshake, true); + else + hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() - macSz, + macSz, handshake, true); + + // read mac and fill + opaque mac[SHA_LEN]; // max size + int digestSz = ssl.getCrypto().get_digest().get_digestSize(); + input.read(mac, digestSz); + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + uint ivExtra = 0; + if (ssl.getSecurity().get_parms().cipher_type_ == block) + if (ssl.isTLSv1_1()) + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + + opaque fill; + int padSz = ssl.getSecurity().get_parms().encrypt_size_ - ivExtra - + HANDSHAKE_HEADER - finishedSz - digestSz; + for (int i = 0; i < padSz; i++) + fill = input[AUTO]; + if (input.get_error()) { + ssl.SetError(bad_input); + return; + } + + // verify mac + if (memcmp(mac, verifyMAC, digestSz)) { + ssl.SetError(verify_error); + return; + } + + // update states + ssl.useStates().useHandShake() = handShakeReady; + if (ssl.getSecurity().get_parms().entity_ == client_end) + ssl.useStates().useClient() = serverFinishedComplete; + else + ssl.useStates().useServer() = clientFinishedComplete; +} + + +Finished::Finished() +{ + set_length(FINISHED_SZ); +} + + +uint8* Finished::set_md5() +{ + return hashes_.md5_; +} + + +uint8* Finished::set_sha() +{ + return hashes_.sha_; +} + + +input_buffer& Finished::set(input_buffer& in) +{ + return in >> *this; +} + + +output_buffer& Finished::get(output_buffer& out) const +{ + return out << *this; +} + + +HandShakeType Finished::get_type() const +{ + return finished; +} + + +void clean(volatile opaque* p, uint sz, RandomPool& ran) +{ + uint i(0); + + for (i = 0; i < sz; ++i) + p[i] = 0; + + ran.Fill(const_cast(p), sz); + + for (i = 0; i < sz; ++i) + p[i] = 0; +} + + + +Connection::Connection(ProtocolVersion v, RandomPool& ran) + : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0), + pre_secret_len_(0), send_server_key_(false), master_clean_(false), + TLS_(v.major_ >= 3 && v.minor_ >= 1), + TLSv1_1_(v.major_ >= 3 && v.minor_ >= 2), compression_(false), + version_(v), random_(ran) +{ + memset(sessionID_, 0, sizeof(sessionID_)); +} + + +Connection::~Connection() +{ + CleanMaster(); CleanPreMaster(); ysArrayDelete(pre_master_secret_); +} + + +void Connection::AllocPreSecret(uint sz) +{ + pre_master_secret_ = NEW_YS opaque[pre_secret_len_ = sz]; +} + + +void Connection::TurnOffTLS() +{ + TLS_ = false; + version_.minor_ = 0; +} + + +void Connection::TurnOffTLS1_1() +{ + TLSv1_1_ = false; + version_.minor_ = 1; +} + + +// wipeout master secret +void Connection::CleanMaster() +{ + if (!master_clean_) { + volatile opaque* p = master_secret_; + clean(p, SECRET_LEN, random_); + master_clean_ = true; + } +} + + +// wipeout pre master secret +void Connection::CleanPreMaster() +{ + if (pre_master_secret_) { + volatile opaque* p = pre_master_secret_; + clean(p, pre_secret_len_, random_); + + ysArrayDelete(pre_master_secret_); + pre_master_secret_ = 0; + } +} + + +// Create functions for message factory +Message* CreateCipherSpec() { return NEW_YS ChangeCipherSpec; } +Message* CreateAlert() { return NEW_YS Alert; } +Message* CreateHandShake() { return NEW_YS HandShakeHeader; } +Message* CreateData() { return NEW_YS Data; } + +// Create functions for handshake factory +HandShakeBase* CreateHelloRequest() { return NEW_YS HelloRequest; } +HandShakeBase* CreateClientHello() { return NEW_YS ClientHello; } +HandShakeBase* CreateServerHello() { return NEW_YS ServerHello; } +HandShakeBase* CreateCertificate() { return NEW_YS Certificate; } +HandShakeBase* CreateServerKeyExchange() { return NEW_YS ServerKeyExchange;} +HandShakeBase* CreateCertificateRequest() { return NEW_YS + CertificateRequest; } +HandShakeBase* CreateServerHelloDone() { return NEW_YS ServerHelloDone; } +HandShakeBase* CreateCertificateVerify() { return NEW_YS CertificateVerify;} +HandShakeBase* CreateClientKeyExchange() { return NEW_YS ClientKeyExchange;} +HandShakeBase* CreateFinished() { return NEW_YS Finished; } + +// Create functions for server key exchange factory +ServerKeyBase* CreateRSAServerKEA() { return NEW_YS RSA_Server; } +ServerKeyBase* CreateDHServerKEA() { return NEW_YS DH_Server; } +ServerKeyBase* CreateFortezzaServerKEA() { return NEW_YS Fortezza_Server; } + +// Create functions for client key exchange factory +ClientKeyBase* CreateRSAClient() { return NEW_YS + EncryptedPreMasterSecret; } +ClientKeyBase* CreateDHClient() { return NEW_YS + ClientDiffieHellmanPublic; } +ClientKeyBase* CreateFortezzaClient() { return NEW_YS FortezzaKeys; } + + +// Constructor calls this to Register compile time callbacks +void InitMessageFactory(MessageFactory& mf) +{ + mf.Reserve(4); + mf.Register(alert, CreateAlert); + mf.Register(change_cipher_spec, CreateCipherSpec); + mf.Register(handshake, CreateHandShake); + mf.Register(application_data, CreateData); +} + + +// Constructor calls this to Register compile time callbacks +void InitHandShakeFactory(HandShakeFactory& hsf) +{ + hsf.Reserve(10); + hsf.Register(hello_request, CreateHelloRequest); + hsf.Register(client_hello, CreateClientHello); + hsf.Register(server_hello, CreateServerHello); + hsf.Register(certificate, CreateCertificate); + hsf.Register(server_key_exchange, CreateServerKeyExchange); + hsf.Register(certificate_request, CreateCertificateRequest); + hsf.Register(server_hello_done, CreateServerHelloDone); + hsf.Register(certificate_verify, CreateCertificateVerify); + hsf.Register(client_key_exchange, CreateClientKeyExchange); + hsf.Register(finished, CreateFinished); +} + + +// Constructor calls this to Register compile time callbacks +void InitServerKeyFactory(ServerKeyFactory& skf) +{ + skf.Reserve(3); + skf.Register(rsa_kea, CreateRSAServerKEA); + skf.Register(diffie_hellman_kea, CreateDHServerKEA); + skf.Register(fortezza_kea, CreateFortezzaServerKEA); +} + + +// Constructor calls this to Register compile time callbacks +void InitClientKeyFactory(ClientKeyFactory& ckf) +{ + ckf.Reserve(3); + ckf.Register(rsa_kea, CreateRSAClient); + ckf.Register(diffie_hellman_kea, CreateDHClient); + ckf.Register(fortezza_kea, CreateFortezzaClient); +} + + +} // namespace diff --git a/mysql/extra/yassl/src/yassl_int.cpp b/mysql/extra/yassl/src/yassl_int.cpp new file mode 100644 index 0000000..a39965c --- /dev/null +++ b/mysql/extra/yassl/src/yassl_int.cpp @@ -0,0 +1,2826 @@ +/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +/* yaSSL internal source implements SSL supporting types not specified in the + * draft along with type conversion functions. + */ + +// First include (the generated) my_config.h, to get correct platform defines. +#include "my_config.h" +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "runtime.hpp" +#include "yassl_int.hpp" +#include "handshake.hpp" +#include "timer.hpp" + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + + +#ifdef YASSL_PURE_C + + void* operator new(size_t sz, yaSSL::new_t) + { + void* ptr = malloc(sz ? sz : 1); + if (!ptr) abort(); + + return ptr; + } + + + void operator delete(void* ptr, yaSSL::new_t) + { + if (ptr) free(ptr); + } + + + void* operator new[](size_t sz, yaSSL::new_t nt) + { + return ::operator new(sz, nt); + } + + + void operator delete[](void* ptr, yaSSL::new_t nt) + { + ::operator delete(ptr, nt); + } + + namespace yaSSL { + + new_t ys; // for yaSSL library new + + } + +#endif // YASSL_PURE_C + +/* for the definition of get_tty_password() */ +#include + +namespace yaSSL { + + + + + + +// convert a 32 bit integer into a 24 bit one +void c32to24(uint32 u32, uint24& u24) +{ + u24[0] = (u32 >> 16) & 0xff; + u24[1] = (u32 >> 8) & 0xff; + u24[2] = u32 & 0xff; +} + + +// convert a 24 bit integer into a 32 bit one +void c24to32(const uint24 u24, uint32& u32) +{ + u32 = 0; + u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; +} + + +// convert with return for ease of use +uint32 c24to32(const uint24 u24) +{ + uint32 ret; + c24to32(u24, ret); + + return ret; +} + + +// using a for opaque since underlying type is unsgined char and o is not a +// good leading identifier + +// convert opaque to 16 bit integer +void ato16(const opaque* c, uint16& u16) +{ + u16 = 0; + u16 = (c[0] << 8) | (c[1]); +} + + +// convert (copy) opaque to 24 bit integer +void ato24(const opaque* c, uint24& u24) +{ + u24[0] = c[0]; + u24[1] = c[1]; + u24[2] = c[2]; +} + + +// convert 16 bit integer to opaque +void c16toa(uint16 u16, opaque* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} + + +// convert 24 bit integer to opaque +void c24toa(const uint24 u24, opaque* c) +{ + c[0] = u24[0]; + c[1] = u24[1]; + c[2] = u24[2]; +} + + +// convert 32 bit integer to opaque +void c32toa(uint32 u32, opaque* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + + +States::States() : recordLayer_(recordReady), handshakeLayer_(preHandshake), + clientState_(serverNull), serverState_(clientNull), + connectState_(CONNECT_BEGIN), acceptState_(ACCEPT_BEGIN), + what_(no_error) {} + +const RecordLayerState& States::getRecord() const +{ + return recordLayer_; +} + + +const HandShakeState& States::getHandShake() const +{ + return handshakeLayer_; +} + + +const ClientState& States::getClient() const +{ + return clientState_; +} + + +const ServerState& States::getServer() const +{ + return serverState_; +} + + +const ConnectState& States::GetConnect() const +{ + return connectState_; +} + + +const AcceptState& States::GetAccept() const +{ + return acceptState_; +} + + +const char* States::getString() const +{ + return errorString_; +} + + +YasslError States::What() const +{ + return what_; +} + + +RecordLayerState& States::useRecord() +{ + return recordLayer_; +} + + +HandShakeState& States::useHandShake() +{ + return handshakeLayer_; +} + + +ClientState& States::useClient() +{ + return clientState_; +} + + +ServerState& States::useServer() +{ + return serverState_; +} + + +ConnectState& States::UseConnect() +{ + return connectState_; +} + + +AcceptState& States::UseAccept() +{ + return acceptState_; +} + + +char* States::useString() +{ + return errorString_; +} + + +void States::SetError(YasslError ye) +{ + what_ = ye; +} + + +// mark message recvd, check for duplicates, return 0 on success +int States::SetMessageRecvd(HandShakeType hst) +{ + switch (hst) { + case hello_request: + break; // could send more than one + + case client_hello: + if (recvdMessages_.gotClientHello_) + return -1; + recvdMessages_.gotClientHello_ = 1; + break; + + case server_hello: + if (recvdMessages_.gotServerHello_) + return -1; + recvdMessages_.gotServerHello_ = 1; + break; + + case certificate: + if (recvdMessages_.gotCert_) + return -1; + recvdMessages_.gotCert_ = 1; + break; + + case server_key_exchange: + if (recvdMessages_.gotServerKeyExchange_) + return -1; + recvdMessages_.gotServerKeyExchange_ = 1; + break; + + case certificate_request: + if (recvdMessages_.gotCertRequest_) + return -1; + recvdMessages_.gotCertRequest_ = 1; + break; + + case server_hello_done: + if (recvdMessages_.gotServerHelloDone_) + return -1; + recvdMessages_.gotServerHelloDone_ = 1; + break; + + case certificate_verify: + if (recvdMessages_.gotCertVerify_) + return -1; + recvdMessages_.gotCertVerify_ = 1; + break; + + case client_key_exchange: + if (recvdMessages_.gotClientKeyExchange_) + return -1; + recvdMessages_.gotClientKeyExchange_ = 1; + break; + + case finished: + if (recvdMessages_.gotFinished_) + return -1; + recvdMessages_.gotFinished_ = 1; + break; + + + default: + return -1; + + } + + return 0; +} + + +sslFactory::sslFactory() : + messageFactory_(InitMessageFactory), + handShakeFactory_(InitHandShakeFactory), + serverKeyFactory_(InitServerKeyFactory), + clientKeyFactory_(InitClientKeyFactory) +{} + + +const MessageFactory& sslFactory::getMessage() const +{ + return messageFactory_; +} + + +const HandShakeFactory& sslFactory::getHandShake() const +{ + return handShakeFactory_; +} + + +const ServerKeyFactory& sslFactory::getServerKey() const +{ + return serverKeyFactory_; +} + + +const ClientKeyFactory& sslFactory::getClientKey() const +{ + return clientKeyFactory_; +} + + +// extract context parameters and store +SSL::SSL(SSL_CTX* ctx) + : secure_(ctx->getMethod()->getVersion(), crypto_.use_random(), + ctx->getMethod()->getSide(), ctx->GetCiphers(), ctx, + ctx->GetDH_Parms().set_), quietShutdown_(false), has_data_(false) +{ + if (int err = crypto_.get_random().GetError()) { + SetError(YasslError(err)); + return; + } + + CertManager& cm = crypto_.use_certManager(); + cm.CopySelfCert(ctx->getCert()); + + bool serverSide = secure_.use_parms().entity_ == server_end; + + if (ctx->getKey()) { + if (int err = cm.SetPrivateKey(*ctx->getKey())) { + SetError(YasslError(err)); + return; + } + else if (serverSide && !(ctx->GetCiphers().setSuites_)) { + // remove RSA or DSA suites depending on cert key type + ProtocolVersion pv = secure_.get_connection().version_; + + bool removeDH = secure_.use_parms().removeDH_; + bool removeRSA = false; + bool removeDSA = false; + + if (cm.get_keyType() == rsa_sa_algo) + removeDSA = true; + else + removeRSA = true; + secure_.use_parms().SetSuites(pv, removeDH, removeRSA, removeDSA); + } + } + else if (serverSide) { + SetError(no_key_file); + return; + } + + if (ctx->getMethod()->verifyPeer()) + cm.setVerifyPeer(); + if (ctx->getMethod()->verifyNone()) + cm.setVerifyNone(); + if (ctx->getMethod()->failNoCert()) + cm.setFailNoCert(); + cm.setVerifyCallback(ctx->getVerifyCallback()); + + if (serverSide) + crypto_.SetDH(ctx->GetDH_Parms()); + + const SSL_CTX::CertList& ca = ctx->GetCA_List(); + SSL_CTX::CertList::const_iterator first(ca.begin()); + SSL_CTX::CertList::const_iterator last(ca.end()); + + while (first != last) { + if (int err = cm.CopyCaCert(*first)) { + SetError(YasslError(err)); + return; + } + ++first; + } +} + + +// store pending security parameters from Server Hello +void SSL::set_pending(Cipher suite) +{ + Parameters& parms = secure_.use_parms(); + + switch (suite) { + + case TLS_RSA_WITH_AES_256_CBC_SHA: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = sha; + parms.kea_ = rsa_kea; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = AES_256_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS AES(AES_256_KEY_SZ)); + strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_256_CBC_SHA], + MAX_SUITE_NAME); + break; + + case TLS_RSA_WITH_AES_128_CBC_SHA: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = sha; + parms.kea_ = rsa_kea; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = AES_128_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS AES); + strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_128_CBC_SHA], + MAX_SUITE_NAME); + break; + + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + parms.bulk_cipher_algorithm_ = triple_des; + parms.mac_algorithm_ = sha; + parms.kea_ = rsa_kea; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = DES_EDE_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS DES_EDE); + strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_3DES_EDE_CBC_SHA] + , MAX_SUITE_NAME); + break; + + case SSL_RSA_WITH_DES_CBC_SHA: + parms.bulk_cipher_algorithm_ = des; + parms.mac_algorithm_ = sha; + parms.kea_ = rsa_kea; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = DES_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS DES); + strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_DES_CBC_SHA], + MAX_SUITE_NAME); + break; + + case SSL_RSA_WITH_RC4_128_SHA: + parms.bulk_cipher_algorithm_ = rc4; + parms.mac_algorithm_ = sha; + parms.kea_ = rsa_kea; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = RC4_KEY_SZ; + parms.iv_size_ = 0; + parms.cipher_type_ = stream; + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS RC4); + strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_SHA], + MAX_SUITE_NAME); + break; + + case SSL_RSA_WITH_RC4_128_MD5: + parms.bulk_cipher_algorithm_ = rc4; + parms.mac_algorithm_ = md5; + parms.kea_ = rsa_kea; + parms.hash_size_ = MD5_LEN; + parms.key_size_ = RC4_KEY_SZ; + parms.iv_size_ = 0; + parms.cipher_type_ = stream; + crypto_.setDigest(NEW_YS MD5); + crypto_.setCipher(NEW_YS RC4); + strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_MD5], + MAX_SUITE_NAME); + break; + + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + parms.bulk_cipher_algorithm_ = des; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = DES_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS DES); + strncpy(parms.cipher_name_, cipher_names[SSL_DHE_RSA_WITH_DES_CBC_SHA], + MAX_SUITE_NAME); + break; + + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + parms.bulk_cipher_algorithm_ = triple_des; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = DES_EDE_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS DES_EDE); + strncpy(parms.cipher_name_, + cipher_names[SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME); + break; + + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = AES_256_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS AES(AES_256_KEY_SZ)); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME); + break; + + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = AES_128_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS AES); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME); + break; + + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + parms.bulk_cipher_algorithm_ = des; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = DES_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS DES); + strncpy(parms.cipher_name_, cipher_names[SSL_DHE_DSS_WITH_DES_CBC_SHA], + MAX_SUITE_NAME); + break; + + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + parms.bulk_cipher_algorithm_ = triple_des; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = DES_EDE_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS DES_EDE); + strncpy(parms.cipher_name_, + cipher_names[SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME); + break; + + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = AES_256_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS AES(AES_256_KEY_SZ)); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME); + break; + + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = sha; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = SHA_LEN; + parms.key_size_ = AES_128_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS SHA); + crypto_.setCipher(NEW_YS AES); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME); + break; + + case TLS_RSA_WITH_AES_256_CBC_RMD160: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = rmd; + parms.kea_ = rsa_kea; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = AES_256_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS AES(AES_256_KEY_SZ)); + strncpy(parms.cipher_name_, + cipher_names[TLS_RSA_WITH_AES_256_CBC_RMD160], MAX_SUITE_NAME); + break; + + case TLS_RSA_WITH_AES_128_CBC_RMD160: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = rmd; + parms.kea_ = rsa_kea; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = AES_128_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS AES); + strncpy(parms.cipher_name_, + cipher_names[TLS_RSA_WITH_AES_128_CBC_RMD160], MAX_SUITE_NAME); + break; + + case TLS_RSA_WITH_3DES_EDE_CBC_RMD160: + parms.bulk_cipher_algorithm_ = triple_des; + parms.mac_algorithm_ = rmd; + parms.kea_ = rsa_kea; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = DES_EDE_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS DES_EDE); + strncpy(parms.cipher_name_, + cipher_names[TLS_RSA_WITH_3DES_EDE_CBC_RMD160], MAX_SUITE_NAME); + break; + + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160: + parms.bulk_cipher_algorithm_ = triple_des; + parms.mac_algorithm_ = rmd; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = DES_EDE_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS DES_EDE); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160], + MAX_SUITE_NAME); + break; + + case TLS_DHE_RSA_WITH_AES_256_CBC_RMD160: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = rmd; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = AES_256_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS AES(AES_256_KEY_SZ)); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_RMD160], + MAX_SUITE_NAME); + break; + + case TLS_DHE_RSA_WITH_AES_128_CBC_RMD160: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = rmd; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = rsa_sa_algo; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = AES_128_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS AES); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_RMD160], + MAX_SUITE_NAME); + break; + + case TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160: + parms.bulk_cipher_algorithm_ = triple_des; + parms.mac_algorithm_ = rmd; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = DES_EDE_KEY_SZ; + parms.iv_size_ = DES_IV_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS DES_EDE); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160], + MAX_SUITE_NAME); + break; + + case TLS_DHE_DSS_WITH_AES_256_CBC_RMD160: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = rmd; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = AES_256_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS AES(AES_256_KEY_SZ)); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_RMD160], + MAX_SUITE_NAME); + break; + + case TLS_DHE_DSS_WITH_AES_128_CBC_RMD160: + parms.bulk_cipher_algorithm_ = aes; + parms.mac_algorithm_ = rmd; + parms.kea_ = diffie_hellman_kea; + parms.sig_algo_ = dsa_sa_algo; + parms.hash_size_ = RMD_LEN; + parms.key_size_ = AES_128_KEY_SZ; + parms.iv_size_ = AES_BLOCK_SZ; + parms.cipher_type_ = block; + secure_.use_connection().send_server_key_ = true; // eph + crypto_.setDigest(NEW_YS RMD); + crypto_.setCipher(NEW_YS AES); + strncpy(parms.cipher_name_, + cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_RMD160], + MAX_SUITE_NAME); + break; + + default: + SetError(unknown_cipher); + } +} + +#ifdef _WIN32 +typedef volatile LONG yassl_pthread_once_t; +#define YASSL_PTHREAD_ONCE_INIT 0 +#define YASSL_PTHREAD_ONCE_INPROGRESS 1 +#define YASSL_PTHREAD_ONCE_DONE 2 + +int yassl_pthread_once(yassl_pthread_once_t *once_control, + void (*init_routine)(void)) +{ + LONG state; + + /* + Do "dirty" read to find out if initialization is already done, to + save an interlocked operation in common case. Memory barriers are ensured by + Visual C++ volatile implementation. + */ + if (*once_control == YASSL_PTHREAD_ONCE_DONE) + return 0; + + state= InterlockedCompareExchange(once_control, YASSL_PTHREAD_ONCE_INPROGRESS, + YASSL_PTHREAD_ONCE_INIT); + + switch(state) + { + case YASSL_PTHREAD_ONCE_INIT: + /* This is initializer thread */ + (*init_routine)(); + *once_control= YASSL_PTHREAD_ONCE_DONE; + break; + + case YASSL_PTHREAD_ONCE_INPROGRESS: + /* init_routine in progress. Wait for its completion */ + while(*once_control == YASSL_PTHREAD_ONCE_INPROGRESS) + { + Sleep(1); + } + break; + case YASSL_PTHREAD_ONCE_DONE: + /* Nothing to do */ + break; + } + return 0; +} +#else +#define yassl_pthread_once_t pthread_once_t +#if defined(PTHREAD_ONCE_INITIALIZER) +#define YASSL_PTHREAD_ONCE_INIT PTHREAD_ONCE_INITIALIZER +#else +#define YASSL_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#endif +#define yassl_pthread_once(C,F) pthread_once(C,F) +#endif // _WIN32 + +// store peer's random +void SSL::set_random(const opaque* random, ConnectionEnd sender) +{ + if (sender == client_end) + memcpy(secure_.use_connection().client_random_, random, RAN_LEN); + else + memcpy(secure_.use_connection().server_random_, random, RAN_LEN); +} + + +// store client pre master secret +void SSL::set_preMaster(const opaque* pre, uint sz) +{ + uint i(0); // trim leading zeros + uint fullSz(sz); + + while (i++ < fullSz && *pre == 0) { + sz--; + pre++; + } + + if (sz == 0) { + SetError(bad_input); + return; + } + + secure_.use_connection().AllocPreSecret(sz); + memcpy(secure_.use_connection().pre_master_secret_, pre, sz); +} + + +// set yaSSL zlib type compression +int SSL::SetCompression() +{ +#ifdef HAVE_LIBZ + secure_.use_connection().compression_ = true; + return 0; +#else + return -1; // not built in +#endif +} + + +// unset yaSSL zlib type compression +void SSL::UnSetCompression() +{ + secure_.use_connection().compression_ = false; +} + + +// is yaSSL zlib compression on +bool SSL::CompressionOn() const +{ + return secure_.get_connection().compression_; +} + + +// store master secret +void SSL::set_masterSecret(const opaque* sec) +{ + memcpy(secure_.use_connection().master_secret_, sec, SECRET_LEN); +} + +// store server issued id +void SSL::set_sessionID(const opaque* sessionID) +{ + memcpy(secure_.use_connection().sessionID_, sessionID, ID_LEN); + secure_.use_connection().sessionID_Set_ = true; +} + + +// store error +void SSL::SetError(YasslError ye) +{ + states_.SetError(ye); + //strncpy(states_.useString(), e.what(), mySTL::named_exception::NAME_SIZE); + // TODO: add string here +} + + +// set the quiet shutdown mode (close_nofiy not sent or received on shutdown) +void SSL::SetQuietShutdown(bool mode) +{ + quietShutdown_ = mode; +} + + +Buffers& SSL::useBuffers() +{ + return buffers_; +} + + +// locals +namespace { + +// DeriveKeys and MasterSecret helper sets prefix letters +static bool setPrefix(opaque* sha_input, int i) +{ + switch (i) { + case 0: + memcpy(sha_input, "A", 1); + break; + case 1: + memcpy(sha_input, "BB", 2); + break; + case 2: + memcpy(sha_input, "CCC", 3); + break; + case 3: + memcpy(sha_input, "DDDD", 4); + break; + case 4: + memcpy(sha_input, "EEEEE", 5); + break; + case 5: + memcpy(sha_input, "FFFFFF", 6); + break; + case 6: + memcpy(sha_input, "GGGGGGG", 7); + break; + default: + return false; // prefix_error + } + return true; +} + + +const char handshake_order[] = "Out of order HandShake Message!"; + + +} // namespcae for locals + + +void SSL::order_error() +{ + SetError(out_of_order); +} + + +// Create and store the master secret see page 32, 6.1 +void SSL::makeMasterSecret() +{ + if (GetError()) return; + + if (isTLS()) + makeTLSMasterSecret(); + else { + opaque sha_output[SHA_LEN]; + + const uint& preSz = secure_.get_connection().pre_secret_len_; + output_buffer md5_input(preSz + SHA_LEN); + output_buffer sha_input(PREFIX + preSz + 2 * RAN_LEN); + + MD5 md5; + SHA sha; + + md5_input.write(secure_.get_connection().pre_master_secret_, preSz); + + for (int i = 0; i < MASTER_ROUNDS; ++i) { + opaque prefix[PREFIX]; + if (!setPrefix(prefix, i)) { + SetError(prefix_error); + return; + } + + sha_input.set_current(0); + sha_input.write(prefix, i + 1); + + sha_input.write(secure_.get_connection().pre_master_secret_,preSz); + sha_input.write(secure_.get_connection().client_random_, RAN_LEN); + sha_input.write(secure_.get_connection().server_random_, RAN_LEN); + sha.get_digest(sha_output, sha_input.get_buffer(), + sha_input.get_size()); + + md5_input.set_current(preSz); + md5_input.write(sha_output, SHA_LEN); + md5.get_digest(&secure_.use_connection().master_secret_[i*MD5_LEN], + md5_input.get_buffer(), md5_input.get_size()); + } + deriveKeys(); + } + secure_.use_connection().CleanPreMaster(); +} + + +// create TLSv1 master secret +void SSL::makeTLSMasterSecret() +{ + opaque seed[SEED_LEN]; + + memcpy(seed, secure_.get_connection().client_random_, RAN_LEN); + memcpy(&seed[RAN_LEN], secure_.get_connection().server_random_, RAN_LEN); + + PRF(secure_.use_connection().master_secret_, SECRET_LEN, + secure_.get_connection().pre_master_secret_, + secure_.get_connection().pre_secret_len_, + master_label, MASTER_LABEL_SZ, + seed, SEED_LEN); + + deriveTLSKeys(); +} + + +// derive mac, write, and iv keys for server and client, see page 34, 6.2.2 +void SSL::deriveKeys() +{ + int length = 2 * secure_.get_parms().hash_size_ + + 2 * secure_.get_parms().key_size_ + + 2 * secure_.get_parms().iv_size_; + int rounds = (length + MD5_LEN - 1 ) / MD5_LEN; + input_buffer key_data(rounds * MD5_LEN); + + opaque sha_output[SHA_LEN]; + opaque md5_input[SECRET_LEN + SHA_LEN]; + opaque sha_input[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN]; + + MD5 md5; + SHA sha; + + memcpy(md5_input, secure_.get_connection().master_secret_, SECRET_LEN); + + for (int i = 0; i < rounds; ++i) { + int j = i + 1; + if (!setPrefix(sha_input, i)) { + SetError(prefix_error); + return; + } + + memcpy(&sha_input[j], secure_.get_connection().master_secret_, + SECRET_LEN); + memcpy(&sha_input[j+SECRET_LEN], + secure_.get_connection().server_random_, RAN_LEN); + memcpy(&sha_input[j + SECRET_LEN + RAN_LEN], + secure_.get_connection().client_random_, RAN_LEN); + sha.get_digest(sha_output, sha_input, + sizeof(sha_input) - KEY_PREFIX + j); + + memcpy(&md5_input[SECRET_LEN], sha_output, SHA_LEN); + md5.get_digest(key_data.get_buffer() + i * MD5_LEN, + md5_input, sizeof(md5_input)); + } + storeKeys(key_data.get_buffer()); +} + + +// derive mac, write, and iv keys for server and client +void SSL::deriveTLSKeys() +{ + int length = 2 * secure_.get_parms().hash_size_ + + 2 * secure_.get_parms().key_size_ + + 2 * secure_.get_parms().iv_size_; + opaque seed[SEED_LEN]; + input_buffer key_data(length); + + memcpy(seed, secure_.get_connection().server_random_, RAN_LEN); + memcpy(&seed[RAN_LEN], secure_.get_connection().client_random_, RAN_LEN); + + PRF(key_data.get_buffer(), length, secure_.get_connection().master_secret_, + SECRET_LEN, key_label, KEY_LABEL_SZ, seed, SEED_LEN); + + storeKeys(key_data.get_buffer()); +} + + +// store mac, write, and iv keys for client and server +void SSL::storeKeys(const opaque* key_data) +{ + int sz = secure_.get_parms().hash_size_; + memcpy(secure_.use_connection().client_write_MAC_secret_, key_data, sz); + int i = sz; + memcpy(secure_.use_connection().server_write_MAC_secret_,&key_data[i], sz); + i += sz; + + sz = secure_.get_parms().key_size_; + memcpy(secure_.use_connection().client_write_key_, &key_data[i], sz); + i += sz; + memcpy(secure_.use_connection().server_write_key_, &key_data[i], sz); + i += sz; + + sz = secure_.get_parms().iv_size_; + memcpy(secure_.use_connection().client_write_IV_, &key_data[i], sz); + i += sz; + memcpy(secure_.use_connection().server_write_IV_, &key_data[i], sz); + + setKeys(); +} + + +// set encrypt/decrypt keys and ivs +void SSL::setKeys() +{ + Connection& conn = secure_.use_connection(); + + if (secure_.get_parms().entity_ == client_end) { + crypto_.use_cipher().set_encryptKey(conn.client_write_key_, + conn.client_write_IV_); + crypto_.use_cipher().set_decryptKey(conn.server_write_key_, + conn.server_write_IV_); + } + else { + crypto_.use_cipher().set_encryptKey(conn.server_write_key_, + conn.server_write_IV_); + crypto_.use_cipher().set_decryptKey(conn.client_write_key_, + conn.client_write_IV_); + } +} + + + +// local functors +namespace yassl_int_cpp_local1 { // for explicit templates + +struct SumData { + uint total_; + SumData() : total_(0) {} + void operator()(input_buffer* data) { total_ += data->get_remaining(); } +}; + + +struct SumBuffer { + uint total_; + SumBuffer() : total_(0) {} + void operator()(output_buffer* buffer) { total_ += buffer->get_size(); } +}; + +} // namespace for locals +using namespace yassl_int_cpp_local1; + + +uint SSL::bufferedData() +{ + return STL::for_each(buffers_.getData().begin(),buffers_.getData().end(), + SumData()).total_; +} + + +// use input buffer to fill data +void SSL::fillData(Data& data) +{ + if (GetError()) return; + uint dataSz = data.get_length(); // input, data size to fill + size_t elements = buffers_.getData().size(); + + data.set_length(0); // output, actual data filled + dataSz = min(dataSz, bufferedData()); + + for (size_t i = 0; i < elements; i++) { + input_buffer* front = buffers_.getData().front(); + uint frontSz = front->get_remaining(); + uint readSz = min(dataSz - data.get_length(), frontSz); + + front->read(data.set_buffer() + data.get_length(), readSz); + data.set_length(data.get_length() + readSz); + + if (readSz == frontSz) { + buffers_.useData().pop_front(); + ysDelete(front); + } + if (data.get_length() == dataSz) + break; + } + + if (buffers_.getData().size() == 0) has_data_ = false; // none left +} + + +// like Fill but keep data in buffer +void SSL::PeekData(Data& data) +{ + if (GetError()) return; + uint dataSz = data.get_length(); // input, data size to fill + size_t elements = buffers_.getData().size(); + + data.set_length(0); // output, actual data filled + dataSz = min(dataSz, bufferedData()); + + Buffers::inputList::iterator front = buffers_.useData().begin(); + + while (elements) { + uint frontSz = (*front)->get_remaining(); + uint readSz = min(dataSz - data.get_length(), frontSz); + uint before = (*front)->get_current(); + + (*front)->read(data.set_buffer() + data.get_length(), readSz); + data.set_length(data.get_length() + readSz); + (*front)->set_current(before); + + if (data.get_length() == dataSz) + break; + + elements--; + front++; + } +} + + +// flush output buffer +void SSL::flushBuffer() +{ + if (GetError()) return; + + uint sz = STL::for_each(buffers_.getHandShake().begin(), + buffers_.getHandShake().end(), + SumBuffer()).total_; + output_buffer out(sz); + size_t elements = buffers_.getHandShake().size(); + + for (size_t i = 0; i < elements; i++) { + output_buffer* front = buffers_.getHandShake().front(); + out.write(front->get_buffer(), front->get_size()); + + buffers_.useHandShake().pop_front(); + ysDelete(front); + } + Send(out.get_buffer(), out.get_size()); +} + + +void SSL::Send(const byte* buffer, uint sz) +{ + unsigned int sent = 0; + + if (socket_.send(buffer, sz, sent) != sz) { + if (socket_.WouldBlock()) { + buffers_.SetOutput(NEW_YS output_buffer(sz - sent, buffer + sent, + sz - sent)); + SetError(YasslError(SSL_ERROR_WANT_WRITE)); + } + else + SetError(send_error); + } +} + + +void SSL::SendWriteBuffered() +{ + output_buffer* out = buffers_.TakeOutput(); + + if (out) { + mySTL::auto_ptr tmp(out); + Send(out->get_buffer(), out->get_size()); + } +} + + +// get sequence number, if verify get peer's +uint SSL::get_SEQIncrement(bool verify) +{ + if (verify) + return secure_.use_connection().peer_sequence_number_++; + else + return secure_.use_connection().sequence_number_++; +} + + +const byte* SSL::get_macSecret(bool verify) +{ + if ( (secure_.get_parms().entity_ == client_end && !verify) || + (secure_.get_parms().entity_ == server_end && verify) ) + return secure_.get_connection().client_write_MAC_secret_; + else + return secure_.get_connection().server_write_MAC_secret_; +} + + +void SSL::verifyState(const RecordLayerHeader& rlHeader) +{ + if (GetError()) return; + + if (rlHeader.version_.major_ != 3 || rlHeader.version_.minor_ > 2) { + SetError(badVersion_error); + return; + } + + if (states_.getRecord() == recordNotReady || + (rlHeader.type_ == application_data && // data and handshake + states_.getHandShake() != handShakeReady) ) // isn't complete yet + SetError(record_layer); +} + + +void SSL::verifyState(const HandShakeHeader& hsHeader) +{ + if (GetError()) return; + + if (states_.getHandShake() == handShakeNotReady) { + SetError(handshake_layer); + return; + } + + if (states_.SetMessageRecvd(hsHeader.get_handshakeType()) != 0) { + order_error(); + return; + } + + if (secure_.get_parms().entity_ == client_end) + verifyClientState(hsHeader.get_handshakeType()); + else + verifyServerState(hsHeader.get_handshakeType()); +} + + +void SSL::verifyState(ClientState cs) +{ + if (GetError()) return; + if (states_.getClient() != cs) order_error(); +} + + +void SSL::verifyState(ServerState ss) +{ + if (GetError()) return; + if (states_.getServer() != ss) order_error(); +} + + +void SSL::verfiyHandShakeComplete() +{ + if (GetError()) return; + if (states_.getHandShake() != handShakeReady) order_error(); +} + + +void SSL::verifyClientState(HandShakeType hsType) +{ + if (GetError()) return; + + switch(hsType) { + case server_hello : + if (states_.getClient() != serverNull) + order_error(); + break; + case certificate : + if (states_.getClient() != serverHelloComplete) + order_error(); + break; + case server_key_exchange : + if (states_.getClient() != serverCertComplete) + order_error(); + break; + case certificate_request : + if (states_.getClient() != serverCertComplete && + states_.getClient() != serverKeyExchangeComplete) + order_error(); + break; + case server_hello_done : + if (states_.getClient() != serverCertComplete && + states_.getClient() != serverKeyExchangeComplete) + order_error(); + break; + case finished : + if (states_.getClient() != serverHelloDoneComplete || + secure_.get_parms().pending_) // no change + order_error(); // cipher yet + break; + default : + order_error(); + }; +} + + +void SSL::verifyServerState(HandShakeType hsType) +{ + if (GetError()) return; + + switch(hsType) { + case client_hello : + if (states_.getServer() != clientNull) + order_error(); + break; + case certificate : + if (states_.getServer() != clientHelloComplete) + order_error(); + break; + case client_key_exchange : + if (states_.getServer() != clientHelloComplete) + order_error(); + break; + case certificate_verify : + if (states_.getServer() != clientKeyExchangeComplete) + order_error(); + break; + case finished : + if (states_.getServer() != clientKeyExchangeComplete || + secure_.get_parms().pending_) // no change + order_error(); // cipher yet + break; + default : + order_error(); + }; +} + + +// try to find a suite match +void SSL::matchSuite(const opaque* peer, uint length) +{ + if (length == 0 || (length % 2) != 0) { + SetError(bad_input); + return; + } + + // start with best, if a match we are good, Ciphers are at odd index + // since all SSL and TLS ciphers have 0x00 first byte + for (uint i = 1; i < secure_.get_parms().suites_size_; i += 2) + for (uint j = 0; (j + 1) < length; j+= 2) { + if (peer[j] != 0x00) { + continue; // only 0x00 first byte supported + } + + if (secure_.use_parms().suites_[i] == peer[j + 1]) { + secure_.use_parms().suite_[0] = 0x00; + secure_.use_parms().suite_[1] = peer[j + 1]; + return; + } + } + + SetError(match_error); +} + + +void SSL::set_session(SSL_SESSION* s) +{ + if (getSecurity().GetContext()->GetSessionCacheOff()) + return; + + if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) { + secure_.set_resuming(true); + crypto_.use_certManager().setPeerX509(s->GetPeerX509()); + } +} + + +const Crypto& SSL::getCrypto() const +{ + return crypto_; +} + + +const Security& SSL::getSecurity() const +{ + return secure_; +} + + +const States& SSL::getStates() const +{ + return states_; +} + + +const sslHashes& SSL::getHashes() const +{ + return hashes_; +} + + +const sslFactory& SSL::getFactory() const +{ + return GetSSL_Factory(); +} + + +const Socket& SSL::getSocket() const +{ + return socket_; +} + + +YasslError SSL::GetError() const +{ + return states_.What(); +} + + +bool SSL::GetQuietShutdown() const +{ + return quietShutdown_; +} + + +bool SSL::GetMultiProtocol() const +{ + return secure_.GetContext()->getMethod()->multipleProtocol(); +} + + +Crypto& SSL::useCrypto() +{ + return crypto_; +} + + +Security& SSL::useSecurity() +{ + return secure_; +} + + +States& SSL::useStates() +{ + return states_; +} + + +sslHashes& SSL::useHashes() +{ + return hashes_; +} + + +Socket& SSL::useSocket() +{ + return socket_; +} + + +Log& SSL::useLog() +{ + return log_; +} + + +bool SSL::isTLS() const +{ + return secure_.get_connection().TLS_; +} + + +bool SSL::isTLSv1_1() const +{ + return secure_.get_connection().TLSv1_1_; +} + + +// is there buffered data available, optimization to remove iteration on buffer +bool SSL::HasData() const +{ + return has_data_; +} + + +void SSL::addData(input_buffer* data) +{ + buffers_.useData().push_back(data); + if (!has_data_) has_data_ = true; +} + + +void SSL::addBuffer(output_buffer* b) +{ + buffers_.useHandShake().push_back(b); +} + + +void SSL_SESSION::CopyX509(X509* x) +{ + if (x == 0) return; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_TIME* before = x->GetBefore(); + ASN1_TIME* after = x->GetAfter(); + + peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), + before, after, + issuer->GetCnPosition(), issuer->GetCnLength(), + subject->GetCnPosition(), subject->GetCnLength()); +} + + +// store connection parameters +SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran) + : timeout_(DEFAULT_TIMEOUT), random_(ran), peerX509_(0) +{ + const Connection& conn = ssl.getSecurity().get_connection(); + + memcpy(sessionID_, conn.sessionID_, ID_LEN); + memcpy(master_secret_, conn.master_secret_, SECRET_LEN); + memcpy(suite_, ssl.getSecurity().get_parms().suite_, SUITE_LEN); + + bornOn_ = lowResTimer(); + + CopyX509(ssl.getCrypto().get_certManager().get_peerX509()); +} + + +// for resumption copy in ssl::parameters +SSL_SESSION::SSL_SESSION(RandomPool& ran) + : bornOn_(0), timeout_(0), random_(ran), peerX509_(0) +{ + memset(sessionID_, 0, ID_LEN); + memset(master_secret_, 0, SECRET_LEN); + memset(suite_, 0, SUITE_LEN); +} + + +SSL_SESSION& SSL_SESSION::operator=(const SSL_SESSION& that) +{ + memcpy(sessionID_, that.sessionID_, ID_LEN); + memcpy(master_secret_, that.master_secret_, SECRET_LEN); + memcpy(suite_, that.suite_, SUITE_LEN); + + bornOn_ = that.bornOn_; + timeout_ = that.timeout_; + + if (peerX509_) { + ysDelete(peerX509_); + peerX509_ = 0; + } + CopyX509(that.peerX509_); + + return *this; +} + + +const opaque* SSL_SESSION::GetID() const +{ + return sessionID_; +} + + +const opaque* SSL_SESSION::GetSecret() const +{ + return master_secret_; +} + + +const Cipher* SSL_SESSION::GetSuite() const +{ + return suite_; +} + + +X509* SSL_SESSION::GetPeerX509() const +{ + return peerX509_; +} + + +uint SSL_SESSION::GetBornOn() const +{ + return bornOn_; +} + + +uint SSL_SESSION::GetTimeOut() const +{ + return timeout_; +} + + +void SSL_SESSION::SetTimeOut(uint t) +{ + timeout_ = t; +} + + +extern void clean(volatile opaque*, uint, RandomPool&); + + +// clean up secret data +SSL_SESSION::~SSL_SESSION() +{ + volatile opaque* p = master_secret_; + clean(p, SECRET_LEN, random_); + + ysDelete(peerX509_); +} + + +static Sessions* sessionsInstance = 0; +static yassl_pthread_once_t session_created= YASSL_PTHREAD_ONCE_INIT; + +void Session_initialize() +{ + sessionsInstance = NEW_YS Sessions; +} + +extern "C" +{ + static void c_session_initialize() { Session_initialize(); } +} + + +Sessions& GetSessions() +{ + yassl_pthread_once(&session_created, c_session_initialize); + return *sessionsInstance; +} + + +static sslFactory* sslFactoryInstance = 0; + +sslFactory& GetSSL_Factory() +{ + if (!sslFactoryInstance) + sslFactoryInstance = NEW_YS sslFactory; + return *sslFactoryInstance; +} + + +static Errors* errorsInstance = 0; + +Errors& GetErrors() +{ + if (!errorsInstance) + errorsInstance = NEW_YS Errors; + return *errorsInstance; +} + + +typedef Mutex::Lock Lock; + + + +void Sessions::add(const SSL& ssl) +{ + if (ssl.getSecurity().get_connection().sessionID_Set_) { + Lock guard(mutex_); + list_.push_back(NEW_YS SSL_SESSION(ssl, random_)); + count_++; + } + + if (count_ > SESSION_FLUSH_COUNT) + if (!ssl.getSecurity().GetContext()->GetSessionCacheFlushOff()) + Flush(); +} + + +Sessions::~Sessions() +{ + STL::for_each(list_.begin(), list_.end(), del_ptr_zero()); +} + + +// locals +namespace yassl_int_cpp_local2 { // for explicit templates + +typedef STL::list::iterator sess_iterator; +typedef STL::list::iterator thr_iterator; + +struct sess_match { + const opaque* id_; + explicit sess_match(const opaque* p) : id_(p) {} + + bool operator()(SSL_SESSION* sess) + { + if ( memcmp(sess->GetID(), id_, ID_LEN) == 0) + return true; + return false; + } +}; + + +THREAD_ID_T GetSelf() +{ +#ifndef _POSIX_THREADS + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +struct thr_match { + THREAD_ID_T id_; + explicit thr_match() : id_(GetSelf()) {} + + bool operator()(ThreadError thr) + { + if (thr.threadID_ == id_) + return true; + return false; + } +}; + + +} // local namespace +using namespace yassl_int_cpp_local2; + + +// lookup session by id, return a copy if space provided +SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy) +{ + Lock guard(mutex_); + sess_iterator find = STL::find_if(list_.begin(), list_.end(), + sess_match(id)); + if (find != list_.end()) { + uint current = lowResTimer(); + if ( ((*find)->GetBornOn() + (*find)->GetTimeOut()) < current) { + del_ptr_zero()(*find); + list_.erase(find); + return 0; + } + if (copy) + *copy = *(*find); + return *find; + } + return 0; +} + + +// remove a session by id +void Sessions::remove(const opaque* id) +{ + Lock guard(mutex_); + sess_iterator find = STL::find_if(list_.begin(), list_.end(), + sess_match(id)); + if (find != list_.end()) { + del_ptr_zero()(*find); + list_.erase(find); + } +} + + +// flush expired sessions from cache +void Sessions::Flush() +{ + Lock guard(mutex_); + sess_iterator next = list_.begin(); + uint current = lowResTimer(); + + while (next != list_.end()) { + sess_iterator si = next; + ++next; + if ( ((*si)->GetBornOn() + (*si)->GetTimeOut()) < current) { + del_ptr_zero()(*si); + list_.erase(si); + } + } + count_ = 0; // reset flush counter +} + + +// remove a self thread error +void Errors::Remove() +{ + Lock guard(mutex_); + thr_iterator find = STL::find_if(list_.begin(), list_.end(), + thr_match()); + if (find != list_.end()) + list_.erase(find); +} + + +// lookup self error code +int Errors::Lookup(bool peek) +{ + Lock guard(mutex_); + thr_iterator find = STL::find_if(list_.begin(), list_.end(), + thr_match()); + if (find != list_.end()) { + int ret = find->errorID_; + if (!peek) + list_.erase(find); + return ret; + } + else + return 0; +} + + +// add a new error code for self +void Errors::Add(int error) +{ + ThreadError add; + add.errorID_ = error; + add.threadID_ = GetSelf(); + + Remove(); // may have old error + + Lock guard(mutex_); + list_.push_back(add); +} + + +SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv, bool multiProto) + : version_(pv), side_(ce), verifyPeer_(false), verifyNone_(false), + failNoCert_(false), multipleProtocol_(multiProto) +{} + + +ProtocolVersion SSL_METHOD::getVersion() const +{ + return version_; +} + + +ConnectionEnd SSL_METHOD::getSide() const +{ + return side_; +} + + +void SSL_METHOD::setVerifyPeer() +{ + verifyPeer_ = true; +} + + +void SSL_METHOD::setVerifyNone() +{ + verifyNone_ = true; +} + + +void SSL_METHOD::setFailNoCert() +{ + failNoCert_ = true; +} + + +bool SSL_METHOD::verifyPeer() const +{ + return verifyPeer_; +} + + +bool SSL_METHOD::verifyNone() const +{ + return verifyNone_; +} + + +bool SSL_METHOD::failNoCert() const +{ + return failNoCert_; +} + + +bool SSL_METHOD::multipleProtocol() const +{ + return multipleProtocol_; +} + + +/** Implement a my_strdup replacement, so we can reuse get_password() */ +extern "C" char *yassl_mysql_strdup(const char *from, int) +{ + return from ? strdup(from) : NULL; +} + + +extern "C" +{ +int +default_password_callback(char * buffer, int size_arg, int rwflag, + void * /* unused: callback_data */) +{ + char *passwd; + size_t passwd_len, size= (size_t) size_arg; + + passwd= ::yassl_mysql_get_tty_password_ext("Enter PEM pass phrase:", + yassl_mysql_strdup); + + if (!passwd) + return 0; + + passwd_len= strlen(passwd); + + if (!passwd_len) + return 0; + + if (size > 0) + { + size_t result_len= size - 1 > passwd_len ? + passwd_len : size - 1; + memcpy(buffer, passwd, result_len); + buffer[result_len]= 0; + } + free(passwd); + return passwd_len; +} +} + +SSL_CTX::SSL_CTX(SSL_METHOD* meth) + : method_(meth), certificate_(0), privateKey_(0), + passwordCb_(default_password_callback), + userData_(0), sessionCacheOff_(false), sessionCacheFlushOff_(false), + verifyCallback_(0) +{} + + +SSL_CTX::~SSL_CTX() +{ + ysDelete(method_); + ysDelete(certificate_); + ysDelete(privateKey_); + + STL::for_each(caList_.begin(), caList_.end(), del_ptr_zero()); +} + + +void SSL_CTX::AddCA(x509* ca) +{ + caList_.push_back(ca); +} + + +const SSL_CTX::CertList& +SSL_CTX::GetCA_List() const +{ + return caList_; +} + + +VerifyCallback SSL_CTX::getVerifyCallback() const +{ + return verifyCallback_; +} + + +const x509* SSL_CTX::getCert() const +{ + return certificate_; +} + + +const x509* SSL_CTX::getKey() const +{ + return privateKey_; +} + + +const SSL_METHOD* SSL_CTX::getMethod() const +{ + return method_; +} + + +const Ciphers& SSL_CTX::GetCiphers() const +{ + return ciphers_; +} + + +const DH_Parms& SSL_CTX::GetDH_Parms() const +{ + return dhParms_; +} + + +const Stats& SSL_CTX::GetStats() const +{ + return stats_; +} + + +pem_password_cb SSL_CTX::GetPasswordCb() const +{ + return passwordCb_; +} + + +void SSL_CTX::SetPasswordCb(pem_password_cb cb) +{ + passwordCb_ = cb; +} + + +void* SSL_CTX::GetUserData() const +{ + return userData_; +} + + +bool SSL_CTX::GetSessionCacheOff() const +{ + return sessionCacheOff_; +} + + +bool SSL_CTX::GetSessionCacheFlushOff() const +{ + return sessionCacheFlushOff_; +} + + +void SSL_CTX::SetUserData(void* data) +{ + userData_ = data; +} + + +void SSL_CTX::SetSessionCacheOff() +{ + sessionCacheOff_ = true; +} + + +void SSL_CTX::SetMethod(SSL_METHOD* meth) +{ + if(method_) + ysDelete(method_); + method_= meth; +} + + +void SSL_CTX::SetSessionCacheFlushOff() +{ + sessionCacheFlushOff_ = true; +} + + +void SSL_CTX::setVerifyPeer() +{ + method_->setVerifyPeer(); +} + + +void SSL_CTX::setVerifyNone() +{ + method_->setVerifyNone(); +} + + +void SSL_CTX::setFailNoCert() +{ + method_->setFailNoCert(); +} + + +void SSL_CTX::setVerifyCallback(VerifyCallback vc) +{ + verifyCallback_ = vc; +} + + +bool SSL_CTX::SetDH(const DH& dh) +{ + dhParms_.p_ = dh.p->int_; + dhParms_.g_ = dh.g->int_; + + return dhParms_.set_ = true; +} + + +bool SSL_CTX::SetCipherList(const char* list) +{ + if (!list) + return false; + + bool ret = false; + char name[MAX_SUITE_NAME]; + + char needle[] = ":"; + char* haystack = const_cast(list); + char* prev; + + const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]); + int idx = 0; + + for(;;) { + size_t len; + prev = haystack; + haystack = strstr(haystack, needle); + + if (!haystack) // last cipher + len = min(sizeof(name), strlen(prev)); + else + len = min(sizeof(name), (size_t)(haystack - prev)); + + strncpy(name, prev, len); + name[(len == sizeof(name)) ? len - 1 : len] = 0; + + for (int i = 0; i < suiteSz; i++) + if (strncmp(name, cipher_names[i], sizeof(name)) == 0) { + + ciphers_.suites_[idx++] = 0x00; // first byte always zero + ciphers_.suites_[idx++] = i; + + if (!ret) ret = true; // found at least one + break; + } + if (!haystack) break; + haystack++; + } + + if (ret) { + ciphers_.setSuites_ = true; + ciphers_.suiteSz_ = idx; + } + + return ret; +} + + +void SSL_CTX::IncrementStats(StatsField fd) +{ + + Lock guard(mutex_); + + switch (fd) { + + case Accept: + ++stats_.accept_; + break; + + case Connect: + ++stats_.connect_; + break; + + case AcceptGood: + ++stats_.acceptGood_; + break; + + case ConnectGood: + ++stats_.connectGood_; + break; + + case AcceptRenegotiate: + ++stats_.acceptRenegotiate_; + break; + + case ConnectRenegotiate: + ++stats_.connectRenegotiate_; + break; + + case Hits: + ++stats_.hits_; + break; + + case CbHits: + ++stats_.cbHits_; + break; + + case CacheFull: + ++stats_.cacheFull_; + break; + + case Misses: + ++stats_.misses_; + break; + + case Timeouts: + ++stats_.timeouts_; + break; + + case Number: + ++stats_.number_; + break; + + case GetCacheSize: + ++stats_.getCacheSize_; + break; + + case VerifyMode: + ++stats_.verifyMode_; + break; + + case VerifyDepth: + ++stats_.verifyDepth_; + break; + + default: + break; + } +} + + +Crypto::Crypto() + : digest_(0), cipher_(0), dh_(0) +{} + + +Crypto::~Crypto() +{ + ysDelete(dh_); + ysDelete(cipher_); + ysDelete(digest_); +} + + +const Digest& Crypto::get_digest() const +{ + return *digest_; +} + + +const BulkCipher& Crypto::get_cipher() const +{ + return *cipher_; +} + + +const DiffieHellman& Crypto::get_dh() const +{ + return *dh_; +} + + +const RandomPool& Crypto::get_random() const +{ + return random_; +} + + +const CertManager& Crypto::get_certManager() const +{ + return cert_; +} + + + +Digest& Crypto::use_digest() +{ + return *digest_; +} + + +BulkCipher& Crypto::use_cipher() +{ + return *cipher_; +} + + +DiffieHellman& Crypto::use_dh() +{ + return *dh_; +} + + +RandomPool& Crypto::use_random() +{ + return random_; +} + + +CertManager& Crypto::use_certManager() +{ + return cert_; +} + + + +void Crypto::SetDH(DiffieHellman* dh) +{ + dh_ = dh; +} + + +void Crypto::SetDH(const DH_Parms& dh) +{ + if (dh.set_) + dh_ = NEW_YS DiffieHellman(dh.p_, dh.g_, random_); +} + + +bool Crypto::DhSet() +{ + return dh_ != 0; +} + + +void Crypto::setDigest(Digest* digest) +{ + digest_ = digest; +} + + +void Crypto::setCipher(BulkCipher* c) +{ + cipher_ = c; +} + + +const MD5& sslHashes::get_MD5() const +{ + return md5HandShake_; +} + + +const SHA& sslHashes::get_SHA() const +{ + return shaHandShake_; +} + + +const Finished& sslHashes::get_verify() const +{ + return verify_; +} + + +const Hashes& sslHashes::get_certVerify() const +{ + return certVerify_; +} + + +MD5& sslHashes::use_MD5(){ + return md5HandShake_; +} + + +SHA& sslHashes::use_SHA() +{ + return shaHandShake_; +} + + +Finished& sslHashes::use_verify() +{ + return verify_; +} + + +Hashes& sslHashes::use_certVerify() +{ + return certVerify_; +} + + +Buffers::Buffers() : prevSent(0), plainSz(0), rawInput_(0), output_(0) +{} + + +Buffers::~Buffers() +{ + STL::for_each(handShakeList_.begin(), handShakeList_.end(), + del_ptr_zero()) ; + STL::for_each(dataList_.begin(), dataList_.end(), + del_ptr_zero()) ; + ysDelete(rawInput_); + ysDelete(output_); +} + + +void Buffers::SetOutput(output_buffer* ob) +{ + output_ = ob; +} + + +void Buffers::SetRawInput(input_buffer* ib) +{ + rawInput_ = ib; +} + + +input_buffer* Buffers::TakeRawInput() +{ + input_buffer* ret = rawInput_; + rawInput_ = 0; + + return ret; +} + + +output_buffer* Buffers::TakeOutput() +{ + output_buffer* ret = output_; + output_ = 0; + + return ret; +} + + +const Buffers::inputList& Buffers::getData() const +{ + return dataList_; +} + + +const Buffers::outputList& Buffers::getHandShake() const +{ + return handShakeList_; +} + + +Buffers::inputList& Buffers::useData() +{ + return dataList_; +} + + +Buffers::outputList& Buffers::useHandShake() +{ + return handShakeList_; +} + + +Security::Security(ProtocolVersion pv, RandomPool& ran, ConnectionEnd ce, + const Ciphers& ciphers, SSL_CTX* ctx, bool haveDH) + : conn_(pv, ran), parms_(ce, ciphers, pv, haveDH), resumeSession_(ran), + ctx_(ctx), resuming_(false) +{} + + +const Connection& Security::get_connection() const +{ + return conn_; +} + + +const SSL_CTX* Security::GetContext() const +{ + return ctx_; +} + + +const Parameters& Security::get_parms() const +{ + return parms_; +} + + +const SSL_SESSION& Security::get_resume() const +{ + return resumeSession_; +} + + +bool Security::get_resuming() const +{ + return resuming_; +} + + +Connection& Security::use_connection() +{ + return conn_; +} + + +Parameters& Security::use_parms() +{ + return parms_; +} + + +SSL_SESSION& Security::use_resume() +{ + return resumeSession_; +} + + +void Security::set_resuming(bool b) +{ + resuming_ = b; +} + + +X509_NAME::X509_NAME(const char* n, size_t sz, int pos, int len) + : name_(0), sz_(sz), cnPosition_(pos), cnLen_(len) +{ + if (sz) { + name_ = NEW_YS char[sz]; + memcpy(name_, n, sz); + } + entry_.data = 0; +} + + +X509_NAME::~X509_NAME() +{ + ysArrayDelete(name_); + ysArrayDelete(entry_.data); +} + + +const char* X509_NAME::GetName() const +{ + return name_; +} + + +size_t X509_NAME::GetLength() const +{ + return sz_; +} + + +X509::X509(const char* i, size_t iSz, const char* s, size_t sSz, + ASN1_STRING *b, ASN1_STRING *a, + int issPos, int issLen, + int subPos, int subLen) + : issuer_(i, iSz, issPos, issLen), subject_(s, sSz, subPos, subLen), + beforeDate_((char *) b->data, b->length, b->type), + afterDate_((char *) a->data, a->length, a->type) +{} + + +X509_NAME* X509::GetIssuer() +{ + return &issuer_; +} + + +X509_NAME* X509::GetSubject() +{ + return &subject_; +} + + +ASN1_TIME* X509::GetBefore() +{ + return beforeDate_.GetString(); +} + + +ASN1_TIME* X509::GetAfter() +{ + return afterDate_.GetString(); +} + + +ASN1_STRING* X509_NAME::GetEntry(int i) +{ + if (i < 0 || i >= int(sz_)) + return 0; + + if (i != cnPosition_ || cnLen_ <= 0) // only entry currently supported + return 0; + + if (cnLen_ > int(sz_-i)) // make sure there's room in read buffer + return 0; + + if (entry_.data) + ysArrayDelete(entry_.data); + entry_.data = NEW_YS byte[cnLen_+1]; // max size; + + memcpy(entry_.data, &name_[i], cnLen_); + entry_.data[cnLen_] = 0; + entry_.length = cnLen_; + entry_.type = 0; + return &entry_; +} + + +StringHolder::StringHolder(const char* str, int sz, byte type) +{ + asnString_.length = sz; + asnString_.data = NEW_YS byte[sz + 1]; + memcpy(asnString_.data, str, sz); + asnString_.type = type; +} + + +StringHolder::~StringHolder() +{ + ysArrayDelete(asnString_.data); +} + + +ASN1_STRING* StringHolder::GetString() +{ + return &asnString_; +} + + +#ifdef HAVE_LIBZ + + void* myAlloc(void* /* opaque */, unsigned int item, unsigned int size) + { + return NEW_YS unsigned char[item * size]; + } + + + void myFree(void* /* opaque */, void* memory) + { + unsigned char* ptr = static_cast(memory); + yaSSL::ysArrayDelete(ptr); + } + + + // put size in front of compressed data + int Compress(const byte* in, int sz, input_buffer& buffer) + { + byte tmp[LENGTH_SZ]; + z_stream c_stream; /* compression stream */ + + buffer.allocate(sz + sizeof(uint16) + COMPRESS_EXTRA); + + c_stream.zalloc = myAlloc; + c_stream.zfree = myFree; + c_stream.opaque = (voidpf)0; + + c_stream.next_in = const_cast(in); + c_stream.avail_in = sz; + c_stream.next_out = buffer.get_buffer() + sizeof(tmp); + c_stream.avail_out = buffer.get_capacity() - sizeof(tmp); + + if (deflateInit(&c_stream, 8) != Z_OK) return -1; + int err = deflate(&c_stream, Z_FINISH); + deflateEnd(&c_stream); + if (err != Z_OK && err != Z_STREAM_END) return -1; + + c16toa(sz, tmp); + memcpy(buffer.get_buffer(), tmp, sizeof(tmp)); + buffer.add_size(c_stream.total_out + sizeof(tmp)); + + return 0; + } + + + // get uncompressed size in front + int DeCompress(input_buffer& in, int sz, input_buffer& out) + { + byte tmp[LENGTH_SZ]; + + tmp[0] = in[AUTO]; + tmp[1] = in[AUTO]; + + uint16 len; + ato16(tmp, len); + + out.allocate(len); + + z_stream d_stream; /* decompression stream */ + + d_stream.zalloc = myAlloc; + d_stream.zfree = myFree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = in.get_buffer() + in.get_current(); + d_stream.avail_in = sz - sizeof(tmp); + d_stream.next_out = out.get_buffer(); + d_stream.avail_out = out.get_capacity(); + + if (inflateInit(&d_stream) != Z_OK) return -1; + int err = inflate(&d_stream, Z_FINISH); + inflateEnd(&d_stream); + if (err != Z_OK && err != Z_STREAM_END) return -1; + + out.add_size(d_stream.total_out); + in.set_current(in.get_current() + sz - sizeof(tmp)); + + return 0; + } + + +#else // LIBZ + + // these versions should never get called + int Compress(const byte* in, int sz, input_buffer& buffer) + { + return -1; + } + + + int DeCompress(input_buffer& in, int sz, input_buffer& out) + { + return -1; + } + + +#endif // LIBZ + + +} // namespace + + + +extern "C" void yaSSL_CleanUp() +{ + TaoCrypt::CleanUp(); + yaSSL::ysDelete(yaSSL::sslFactoryInstance); + yaSSL::ysDelete(yaSSL::sessionsInstance); + yaSSL::ysDelete(yaSSL::errorsInstance); + + // In case user calls more than once, prevent seg fault + yaSSL::sslFactoryInstance = 0; + yaSSL::sessionsInstance = 0; + yaSSL::errorsInstance = 0; +} + + +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION +namespace mySTL { +template yaSSL::yassl_int_cpp_local1::SumData for_each::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local1::SumData); +template yaSSL::yassl_int_cpp_local1::SumBuffer for_each::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer); +template mySTL::list::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::sess_match); +template mySTL::list::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::thr_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::thr_match); +} +#endif + diff --git a/mysql/extra/yassl/taocrypt/COPYING b/mysql/extra/yassl/taocrypt/COPYING new file mode 100644 index 0000000..845980a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/mysql/extra/yassl/taocrypt/README b/mysql/extra/yassl/taocrypt/README new file mode 100644 index 0000000..bd786b7 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/README @@ -0,0 +1,48 @@ +TaoCrypt release 0.9.2 02/5/2007 + + +This release includes bug fixes, portability enhancements, and some +optimiations. + +See 0.9.0 for build instructions. + + + + +******************TaoCrypt release 0.9.0 09/18/2006 + +This is the first release of TaoCrypt, it was previously only included with +yaSSL. TaoCrypt is highly portable and fast, its features include: + +One way hash functions: SHA-1, MD2, MD4, MD5, RIPEMD-160 +Message authentication codes: HMAC +Block Ciphers: DES, Triple-DES, AES, Blowfish, Twofish +Stream Ciphers: ARC4 +Public Key Crypto: RSA, DSA, Diffie-Hellman +Password based key derivation: PBKDF2 from PKCS #5 +Pseudo Random Number Generators +Large Integer Support +Base 16/64 encoding/decoding +DER encoding/decoding +X.509 processing +SSE2 and ia32 asm for the right processors and compilers + + +To build on Unix + + ./configure + make + + To test the build, from the ./test directory run ./test + + +On Windows + + Open the taocrypt project workspace + Choose (Re)Build All + + To test the build, run the test executable + + +Please send any questions or comments to todd@yassl.com. + diff --git a/mysql/extra/yassl/taocrypt/include/aes.hpp b/mysql/extra/yassl/taocrypt/include/aes.hpp new file mode 100644 index 0000000..bccf6e7 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/aes.hpp @@ -0,0 +1,155 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* aes.hpp defines AES +*/ + + +#ifndef TAO_CRYPT_AES_HPP +#define TAO_CRYPT_AES_HPP + +#include "misc.hpp" +#include "modes.hpp" + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_AES_ASM +#endif + + + +namespace TaoCrypt { + + +enum { AES_BLOCK_SIZE = 16 }; + + +// AES encryption and decryption, see FIPS-197 +class AES : public Mode_BASE { +public: + enum { BLOCK_SIZE = AES_BLOCK_SIZE }; + + AES(CipherDir DIR, Mode MODE) + : Mode_BASE(BLOCK_SIZE, DIR, MODE) {} + +#ifdef DO_AES_ASM + void Process(byte*, const byte*, word32); +#endif + void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); + void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } +private: + static const word32 rcon_[]; + + word32 rounds_; + word32 key_[60]; // max size + + static const word32 Te[5][256]; + static const word32 Td[5][256]; + static const byte CTd4[256]; + + static const word32* Te0; + static const word32* Te1; + static const word32* Te2; + static const word32* Te3; + static const word32* Te4; + + static const word32* Td0; + static const word32* Td1; + static const word32* Td2; + static const word32* Td3; + static const word32* Td4; + + void encrypt(const byte*, const byte*, byte*) const; + void AsmEncrypt(const byte*, byte*, void*) const; + void decrypt(const byte*, const byte*, byte*) const; + void AsmDecrypt(const byte*, byte*, void*) const; + + void ProcessAndXorBlock(const byte*, const byte*, byte*) const; + + word32 PreFetchTe() const; + word32 PreFetchTd() const; + word32 PreFetchCTd4() const; + + AES(const AES&); // hide copy + AES& operator=(const AES&); // and assign +}; + + +#if defined(__x86_64__) || defined(_M_X64) || \ + (defined(__ILP32__) && (__ILP32__ >= 1)) + #define TC_CACHE_LINE_SZ 64 +#else + /* default cache line size */ + #define TC_CACHE_LINE_SZ 32 +#endif + +inline word32 AES::PreFetchTe() const +{ + word32 x = 0; + + /* 4 tables of 256 entries */ + for (int i = 0; i < 4; i++) { + /* each entry is 4 bytes */ + for (int j = 0; j < 256; j += TC_CACHE_LINE_SZ/4) { + x &= Te[i][j]; + } + } + + return x; +} + + +inline word32 AES::PreFetchTd() const +{ + word32 x = 0; + + /* 4 tables of 256 entries */ + for (int i = 0; i < 4; i++) { + /* each entry is 4 bytes */ + for (int j = 0; j < 256; j += TC_CACHE_LINE_SZ/4) { + x &= Td[i][j]; + } + } + + return x; +} + + +inline word32 AES::PreFetchCTd4() const +{ + word32 x = 0; + int i; + + for (i = 0; i < 256; i += TC_CACHE_LINE_SZ) { + x &= CTd4[i]; + } + + return x; +} + + +typedef BlockCipher AES_ECB_Encryption; +typedef BlockCipher AES_ECB_Decryption; + +typedef BlockCipher AES_CBC_Encryption; +typedef BlockCipher AES_CBC_Decryption; + + +} // naemspace + +#endif // TAO_CRYPT_AES_HPP diff --git a/mysql/extra/yassl/taocrypt/include/algebra.hpp b/mysql/extra/yassl/taocrypt/include/algebra.hpp new file mode 100644 index 0000000..5ce7038 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/algebra.hpp @@ -0,0 +1,226 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's algebra.h from CryptoPP */ + +#ifndef TAO_CRYPT_ALGEBRA_HPP +#define TAO_CRYPT_ALGEBRA_HPP + +#include "integer.hpp" + +namespace TaoCrypt { + + +// "const Element&" returned by member functions are references +// to internal data members. Since each object may have only +// one such data member for holding results, the following code +// will produce incorrect results: +// abcd = group.Add(group.Add(a,b), group.Add(c,d)); +// But this should be fine: +// abcd = group.Add(a, group.Add(b, group.Add(c,d)); + +// Abstract Group +class TAOCRYPT_NO_VTABLE AbstractGroup : public virtual_base +{ +public: + typedef Integer Element; + + virtual ~AbstractGroup() {} + + virtual bool Equal(const Element &a, const Element &b) const =0; + virtual const Element& Identity() const =0; + virtual const Element& Add(const Element &a, const Element &b) const =0; + virtual const Element& Inverse(const Element &a) const =0; + virtual bool InversionIsFast() const {return false;} + + virtual const Element& Double(const Element &a) const; + virtual const Element& Subtract(const Element &a, const Element &b) const; + virtual Element& Accumulate(Element &a, const Element &b) const; + virtual Element& Reduce(Element &a, const Element &b) const; + + virtual Element ScalarMultiply(const Element &a, const Integer &e) const; + virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, + const Element &y, const Integer &e2) const; + + virtual void SimultaneousMultiply(Element *results, const Element &base, + const Integer *exponents, unsigned int exponentsCount) const; +}; + +// Abstract Ring +class TAOCRYPT_NO_VTABLE AbstractRing : public AbstractGroup +{ +public: + typedef Integer Element; + + AbstractRing() : AbstractGroup() {m_mg.m_pRing = this;} + AbstractRing(const AbstractRing &source) : AbstractGroup() + {m_mg.m_pRing = this;} + AbstractRing& operator=(const AbstractRing &source) {return *this;} + + virtual bool IsUnit(const Element &a) const =0; + virtual const Element& MultiplicativeIdentity() const =0; + virtual const Element& Multiply(const Element&, const Element&) const =0; + virtual const Element& MultiplicativeInverse(const Element &a) const =0; + + virtual const Element& Square(const Element &a) const; + virtual const Element& Divide(const Element &a, const Element &b) const; + + virtual Element Exponentiate(const Element &a, const Integer &e) const; + virtual Element CascadeExponentiate(const Element &x, const Integer &e1, + const Element &y, const Integer &e2) const; + + virtual void SimultaneousExponentiate(Element *results, const Element&, + const Integer *exponents, unsigned int exponentsCount) const; + + virtual const AbstractGroup& MultiplicativeGroup() const + {return m_mg;} + +private: + class MultiplicativeGroupT : public AbstractGroup + { + public: + const AbstractRing& GetRing() const + {return *m_pRing;} + + bool Equal(const Element &a, const Element &b) const + {return GetRing().Equal(a, b);} + + const Element& Identity() const + {return GetRing().MultiplicativeIdentity();} + + const Element& Add(const Element &a, const Element &b) const + {return GetRing().Multiply(a, b);} + + Element& Accumulate(Element &a, const Element &b) const + {return a = GetRing().Multiply(a, b);} + + const Element& Inverse(const Element &a) const + {return GetRing().MultiplicativeInverse(a);} + + const Element& Subtract(const Element &a, const Element &b) const + {return GetRing().Divide(a, b);} + + Element& Reduce(Element &a, const Element &b) const + {return a = GetRing().Divide(a, b);} + + const Element& Double(const Element &a) const + {return GetRing().Square(a);} + + Element ScalarMultiply(const Element &a, const Integer &e) const + {return GetRing().Exponentiate(a, e);} + + Element CascadeScalarMultiply(const Element &x, const Integer &e1, + const Element &y, const Integer &e2) const + {return GetRing().CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousMultiply(Element *results, const Element &base, + const Integer *exponents, unsigned int exponentsCount) const + {GetRing().SimultaneousExponentiate(results, base, exponents, + exponentsCount);} + + const AbstractRing* m_pRing; + }; + + MultiplicativeGroupT m_mg; +}; + + +// Abstract Euclidean Domain +class TAOCRYPT_NO_VTABLE AbstractEuclideanDomain + : public AbstractRing +{ +public: + typedef Integer Element; + + virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, + const Element &d) const =0; + + virtual const Element& Mod(const Element &a, const Element &b) const =0; + virtual const Element& Gcd(const Element &a, const Element &b) const; + +protected: + mutable Element result; +}; + + +// EuclideanDomainOf +class EuclideanDomainOf : public AbstractEuclideanDomain +{ +public: + typedef Integer Element; + + EuclideanDomainOf() {} + + bool Equal(const Element &a, const Element &b) const + {return a==b;} + + const Element& Identity() const + {return Element::Zero();} + + const Element& Add(const Element &a, const Element &b) const + {return result = a+b;} + + Element& Accumulate(Element &a, const Element &b) const + {return a+=b;} + + const Element& Inverse(const Element &a) const + {return result = -a;} + + const Element& Subtract(const Element &a, const Element &b) const + {return result = a-b;} + + Element& Reduce(Element &a, const Element &b) const + {return a-=b;} + + const Element& Double(const Element &a) const + {return result = a.Doubled();} + + const Element& MultiplicativeIdentity() const + {return Element::One();} + + const Element& Multiply(const Element &a, const Element &b) const + {return result = a*b;} + + const Element& Square(const Element &a) const + {return result = a.Squared();} + + bool IsUnit(const Element &a) const + {return a.IsUnit();} + + const Element& MultiplicativeInverse(const Element &a) const + {return result = a.MultiplicativeInverse();} + + const Element& Divide(const Element &a, const Element &b) const + {return result = a/b;} + + const Element& Mod(const Element &a, const Element &b) const + {return result = a%b;} + + void DivisionAlgorithm(Element &r, Element &q, const Element &a, + const Element &d) const + {Element::Divide(r, q, a, d);} + +private: + mutable Element result; +}; + + + +} // namespace + +#endif // TAO_CRYPT_ALGEBRA_HPP diff --git a/mysql/extra/yassl/taocrypt/include/arc4.hpp b/mysql/extra/yassl/taocrypt/include/arc4.hpp new file mode 100644 index 0000000..be64ba4 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/arc4.hpp @@ -0,0 +1,58 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* arc4.hpp defines ARC4 +*/ + + +#ifndef TAO_CRYPT_ARC4_HPP +#define TAO_CRYPT_ARC4_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +// ARC4 encryption and decryption +class ARC4 { +public: + enum { STATE_SIZE = 256 }; + + typedef ARC4 Encryption; + typedef ARC4 Decryption; + + ARC4() {} + + void Process(byte*, const byte*, word32); + void SetKey(const byte*, word32); +private: + byte x_; + byte y_; + byte state_[STATE_SIZE]; + + ARC4(const ARC4&); // hide copy + const ARC4 operator=(const ARC4&); // and assign + + void AsmProcess(byte*, const byte*, word32); +}; + +} // namespace + + +#endif // TAO_CRYPT_ARC4_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/asn.hpp b/mysql/extra/yassl/taocrypt/include/asn.hpp new file mode 100644 index 0000000..28c7c8f --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/asn.hpp @@ -0,0 +1,392 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* asn.hpp provides ASN1 BER, PublicKey, and x509v3 decoding +*/ + + +#ifndef TAO_CRYPT_ASN_HPP +#define TAO_CRYPT_ASN_HPP + + +#include +#include "misc.hpp" +#include "block.hpp" +#include "error.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "list.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + +namespace TaoCrypt { + +// these tags and flags are not complete +enum ASNTag +{ + BOOLEAN = 0x01, + INTEGER = 0x02, + BIT_STRING = 0x03, + OCTET_STRING = 0x04, + TAG_NULL = 0x05, + OBJECT_IDENTIFIER = 0x06, + OBJECT_DESCRIPTOR = 0x07, + EXTERNAL = 0x08, + REAL = 0x09, + ENUMERATED = 0x0a, + UTF8_STRING = 0x0c, + SEQUENCE = 0x10, + SET = 0x11, + NUMERIC_STRING = 0x12, + PRINTABLE_STRING = 0x13, + T61_STRING = 0x14, + VIDEOTEXT_STRING = 0x15, + IA5_STRING = 0x16, + UTC_TIME = 0x17, + GENERALIZED_TIME = 0x18, + GRAPHIC_STRING = 0x19, + VISIBLE_STRING = 0x1a, + GENERAL_STRING = 0x1b, + LONG_LENGTH = 0x80 +}; + +enum ASNIdFlag +{ + UNIVERSAL = 0x00, + DATA = 0x01, + HEADER = 0x02, + CONSTRUCTED = 0x20, + APPLICATION = 0x40, + CONTEXT_SPECIFIC = 0x80, + PRIVATE = 0xc0 +}; + + +enum DNTags +{ + COMMON_NAME = 0x03, // CN + SUR_NAME = 0x04, // SN + COUNTRY_NAME = 0x06, // C + LOCALITY_NAME = 0x07, // L + STATE_NAME = 0x08, // ST + ORG_NAME = 0x0a, // O + ORGUNIT_NAME = 0x0b // OU +}; + + +enum PCKS12_Tags +{ + /* DATA = 1, */ // from ASN1 + SIGNED_DATA = 2, + ENVELOPED_DATA = 3, + SIGNED_AND_ENVELOPED_DATA = 4, + DIGESTED_DATA = 5, + ENCRYPTED_DATA = 6 +}; + + +enum Constants +{ + MIN_DATE_SZ = 13, + MAX_DATE_SZ = 16, + MAX_ALGO_SZ = 16, + MAX_LENGTH_SZ = 5, + MAX_SEQ_SZ = 5, // enum(seq|con) + length(4) + MAX_ALGO_SIZE = 9, + MAX_DIGEST_SZ = 69, // SHA512 + enum(Bit or Octet) + length(4) + DSA_SIG_SZ = 40, + ASN_NAME_MAX = 512 // max total of all included names +}; + + +class Source; +class RSA_PublicKey; +class RSA_PrivateKey; +class DSA_PublicKey; +class DSA_PrivateKey; +class Integer; +class DH; + + +// General BER decoding +class BER_Decoder : public virtual_base { +protected: + Source& source_; +public: + explicit BER_Decoder(Source& s) : source_(s) {} + virtual ~BER_Decoder() {} + + Integer& GetInteger(Integer&); + word32 GetSequence(); + word32 GetSet(); + word32 GetVersion(); + word32 GetExplicitVersion(); + + Error GetError(); +private: + virtual void ReadHeader() = 0; + + BER_Decoder(const BER_Decoder&); // hide copy + BER_Decoder& operator=(const BER_Decoder&); // and assign +}; + + +// RSA Private Key BER Decoder +class RSA_Private_Decoder : public BER_Decoder { +public: + explicit RSA_Private_Decoder(Source& s) : BER_Decoder(s) {} + void Decode(RSA_PrivateKey&); +private: + void ReadHeader(); +}; + + +// RSA Public Key BER Decoder +class RSA_Public_Decoder : public BER_Decoder { +public: + explicit RSA_Public_Decoder(Source& s) : BER_Decoder(s) {} + void Decode(RSA_PublicKey&); +private: + void ReadHeader(); + void ReadHeaderOpenSSL(); +}; + + +// DSA Private Key BER Decoder +class DSA_Private_Decoder : public BER_Decoder { +public: + explicit DSA_Private_Decoder(Source& s) : BER_Decoder(s) {} + void Decode(DSA_PrivateKey&); +private: + void ReadHeader(); +}; + + +// DSA Public Key BER Decoder +class DSA_Public_Decoder : public BER_Decoder { +public: + explicit DSA_Public_Decoder(Source& s) : BER_Decoder(s) {} + void Decode(DSA_PublicKey&); +private: + void ReadHeader(); +}; + + +// DH Key BER Decoder +class DH_Decoder : public BER_Decoder { +public: + explicit DH_Decoder(Source& s) : BER_Decoder(s) {} + void Decode(DH&); +private: + void ReadHeader(); +}; + + +// PKCS12 BER Decoder +class PKCS12_Decoder : public BER_Decoder { +public: + explicit PKCS12_Decoder(Source& s) : BER_Decoder(s) {} + void Decode(); +private: + void ReadHeader(); +}; + + +// General PublicKey +class PublicKey { + byte* key_; + word32 sz_; +public: + explicit PublicKey(const byte* k = 0, word32 s = 0); + ~PublicKey() { tcArrayDelete(key_); } + + const byte* GetKey() const { return key_; } + word32 size() const { return sz_; } + + void SetKey(const byte*); + void SetSize(word32 s); + + void AddToEnd(const byte*, word32); +private: + PublicKey(const PublicKey&); // hide copy + PublicKey& operator=(const PublicKey&); // and assign +}; + + +enum { SHA_SIZE = 20 }; + + +// A Signing Authority +class Signer { + PublicKey key_; + char name_[ASN_NAME_MAX]; + byte hash_[SHA_SIZE]; +public: + Signer(const byte* k, word32 kSz, const char* n, const byte* h); + ~Signer(); + + const PublicKey& GetPublicKey() const { return key_; } + const char* GetName() const { return name_; } + const byte* GetHash() const { return hash_; } + +private: + Signer(const Signer&); // hide copy + Signer& operator=(const Signer&); // and assign +}; + + +typedef STL::list SignerList; + + +enum ContentType { HUH = 651 }; +enum SigType { SHAwDSA = 517, MD2wRSA = 646, MD5wRSA = 648, SHAwRSA = 649, + SHA256wRSA = 655, SHA384wRSA = 656, SHA512wRSA = 657, + SHA256wDSA = 416 }; +enum HashType { MD2h = 646, MD5h = 649, SHAh = 88, SHA256h = 414, SHA384h = 415, + SHA512h = 416 }; +enum KeyType { DSAk = 515, RSAk = 645 }; // sums of algo OID + + +// an x509v Certificate BER Decoder +class CertDecoder : public BER_Decoder { +public: + enum DateType { BEFORE, AFTER }; + enum NameType { ISSUER, SUBJECT }; + enum CertType { CA, USER }; + + explicit CertDecoder(Source&, bool decode = true, SignerList* sl = 0, + bool noVerify = false, CertType ct = USER); + ~CertDecoder(); + + const PublicKey& GetPublicKey() const { return key_; } + KeyType GetKeyType() const { return KeyType(keyOID_); } + const char* GetIssuer() const { return issuer_; } + const char* GetCommonName() const { return subject_; } + const byte* GetHash() const { return subjectHash_; } + const char* GetBeforeDate() const { return beforeDate_; } + byte GetBeforeDateType() const { return beforeDateType_; } + const char* GetAfterDate() const { return afterDate_; } + byte GetAfterDateType() const { return afterDateType_; } + int GetSubjectCnStart() const { return subCnPos_; } + int GetIssuerCnStart() const { return issCnPos_; } + int GetSubjectCnLength() const { return subCnLen_; } + int GetIssuerCnLength() const { return issCnLen_; } + void DecodeToKey(); +private: + PublicKey key_; + word32 certBegin_; // offset to start of cert + word32 sigIndex_; // offset to start of signature + word32 sigLength_; // length of signature + word32 signatureOID_; // sum of algorithm object id + word32 keyOID_; // sum of key algo object id + int subCnPos_; // subject common name start, -1 is none + int subCnLen_; // length of above + int issCnPos_; // issuer common name start, -1 is none + int issCnLen_; // length of above + byte subjectHash_[SHA_SIZE]; // hash of all Names + byte issuerHash_[SHA_SIZE]; // hash of all Names + byte* signature_; + char issuer_[ASN_NAME_MAX]; // Names + char subject_[ASN_NAME_MAX]; // Names + char beforeDate_[MAX_DATE_SZ+1]; // valid before date, +null term + byte beforeDateType_; // beforeDate time type + char afterDate_[MAX_DATE_SZ+1]; // valid after date, +null term + byte afterDateType_; // afterDate time type + bool verify_; // Default to yes, but could be off + + void ReadHeader(); + void Decode(SignerList*, CertType); + void StoreKey(); + void AddDSA(); + bool ValidateSelfSignature(); + bool ValidateSignature(SignerList*); + bool ConfirmSignature(Source&); + void GetKey(); + char* AddTag(char*, const char*, const char*, word32, word32); + void GetName(NameType); + void GetValidity(); + void GetDate(DateType); + void GetCompareHash(const byte*, word32, byte*, word32); + word32 GetAlgoId(); + word32 GetSignature(); + word32 GetDigest(); +}; + + +word32 GetLength(Source&); + +word32 SetLength(word32, byte*); +word32 SetSequence(word32, byte*); + +word32 EncodeDSA_Signature(const byte* signature, byte* output); +word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output); +word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz); + + +// General DER encoding +class DER_Encoder : public virtual_base { +public: + DER_Encoder() {} + virtual ~DER_Encoder() {} + + word32 SetAlgoID(HashType, byte*); + + Error GetError() const { return error_; } +private: + //virtual void WriteHeader() = 0; + Error error_; + + DER_Encoder(const DER_Encoder&); // hide copy + DER_Encoder& operator=(const DER_Encoder&); // and assign +}; + + + +class Signature_Encoder : public DER_Encoder { + const byte* digest_; + word32 digestSz_; + SigType digestOID_; +public: + explicit Signature_Encoder(const byte*, word32, HashType, Source&); + +private: + void WriteHeader(); + word32 SetDigest(const byte*, word32, byte*); + + Signature_Encoder(const Signature_Encoder&); // hide copy + Signature_Encoder& operator=(const Signature_Encoder&); // and assign +}; + + +// Get Cert in PEM format from BEGIN to END +int GetCert(Source&); + +// Get Cert in PEM format from pkcs12 file +int GetPKCS_Cert(const char* password, Source&); + +bool ASN1_TIME_extract(const unsigned char* date, unsigned char format, + tm *parsed_time); + +} // namespace + + +#endif // TAO_CRYPT_ASN_HPP diff --git a/mysql/extra/yassl/taocrypt/include/block.hpp b/mysql/extra/yassl/taocrypt/include/block.hpp new file mode 100644 index 0000000..4f58c82 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/block.hpp @@ -0,0 +1,202 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* block.hpp provides word and byte blocks with configurable allocators +*/ + + +#ifndef TAO_CRYPT_BLOCK_HPP +#define TAO_CRYPT_BLOCK_HPP + +#include "misc.hpp" +#include // memcpy +#include // ptrdiff_t + +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + +namespace TaoCrypt { + + +// a Base class for Allocators +template +class AllocatorBase +{ +public: + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + + pointer address(reference r) const {return (&r);} + const_pointer address(const_reference r) const {return (&r); } + void construct(pointer p, const T& val) {new (p) T(val);} + void destroy(pointer p) {p->~T();} + size_type max_size() const {return ~size_type(0)/sizeof(T);} +protected: +}; + + +// General purpose realloc +template +typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize, + typename A::size_type newSize, bool preserve) +{ + if (oldSize == newSize) + return p; + + if (preserve) { + A b = A(); + typename A::pointer newPointer = b.allocate(newSize, 0); + memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize)); + a.deallocate(p, oldSize); + STL::swap(a, b); + return newPointer; + } + else { + a.deallocate(p, oldSize); + return a.allocate(newSize, 0); + } +} + + +// Allocator that zeros out memory on deletion +template +class AllocatorWithCleanup : public AllocatorBase +{ +public: + typedef typename AllocatorBase::pointer pointer; + typedef typename AllocatorBase::size_type size_type; + + pointer allocate(size_type n, const void* = 0) + { + if (n > this->max_size()) + return 0; + if (n == 0) + return 0; + return NEW_TC T[n]; + } + + void deallocate(void* p, size_type n) + { + memset(p, 0, n * sizeof(T)); + tcArrayDelete((T*)p); + } + + pointer reallocate(T* p, size_type oldSize, size_type newSize, + bool preserve) + { + return StdReallocate(*this, p, oldSize, newSize, preserve); + } + + // VS.NET STL enforces the policy of "All STL-compliant allocators have to + // provide a template class member called rebind". + template struct rebind { typedef AllocatorWithCleanup other;}; +}; + + +// Block class template +template > +class Block { +public: + explicit Block(word32 s = 0) : sz_(s), buffer_(allocator_.allocate(sz_)) + { CleanNew(sz_); } + + Block(const T* buff, word32 s) : sz_(s), buffer_(allocator_.allocate(sz_)) + { memcpy(buffer_, buff, sz_ * sizeof(T)); } + + Block(const Block& that) : sz_(that.sz_), buffer_(allocator_.allocate(sz_)) + { memcpy(buffer_, that.buffer_, sz_ * sizeof(T)); } + + Block& operator=(const Block& that) { + Block tmp(that); + Swap(tmp); + return *this; + } + + T& operator[] (word32 i) { return buffer_[i]; } + const T& operator[] (word32 i) const { return buffer_[i]; } + + T* operator+ (word32 i) { return buffer_ + i; } + const T* operator+ (word32 i) const { return buffer_ + i; } + + word32 size() const { return sz_; } + + T* get_buffer() const { return buffer_; } + T* begin() const { return get_buffer(); } + + void CleanGrow(word32 newSize) + { + if (newSize > sz_) { + buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true); + memset(buffer_ + sz_, 0, (newSize - sz_) * sizeof(T)); + sz_ = newSize; + } + } + + void CleanNew(word32 newSize) + { + New(newSize); + memset(buffer_, 0, sz_ * sizeof(T)); + } + + void New(word32 newSize) + { + buffer_ = allocator_.reallocate(buffer_, sz_, newSize, false); + sz_ = newSize; + } + + void resize(word32 newSize) + { + buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true); + sz_ = newSize; + } + + void Swap(Block& other) { + STL::swap(sz_, other.sz_); + STL::swap(buffer_, other.buffer_); + STL::swap(allocator_, other.allocator_); + } + + ~Block() { allocator_.deallocate(buffer_, sz_); } +private: + A allocator_; + word32 sz_; // size in Ts + T* buffer_; +}; + + +typedef Block ByteBlock; +typedef Block WordBlock; +typedef Block Word32Block; + + +} // namespace + +#endif // TAO_CRYPT_BLOCK_HPP diff --git a/mysql/extra/yassl/taocrypt/include/blowfish.hpp b/mysql/extra/yassl/taocrypt/include/blowfish.hpp new file mode 100644 index 0000000..1f8d058 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/blowfish.hpp @@ -0,0 +1,88 @@ +/* + Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* blowfish.hpp defines Blowfish +*/ + + +#ifndef TAO_CRYPT_BLOWFISH_HPP +#define TAO_CRYPT_BLOWFISH_HPP + +#include "misc.hpp" +#include "modes.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_BLOWFISH_ASM +#endif + + +namespace TaoCrypt { + +enum { BLOWFISH_BLOCK_SIZE = 8 }; + + +// Blowfish encryption and decryption, see +class Blowfish : public Mode_BASE { +public: + enum { BLOCK_SIZE = BLOWFISH_BLOCK_SIZE, ROUNDS = 16 }; + + Blowfish(CipherDir DIR, Mode MODE) + : Mode_BASE(BLOCK_SIZE, DIR, MODE), sbox_(pbox_ + ROUNDS + 2) {} + +#ifdef DO_BLOWFISH_ASM + void Process(byte*, const byte*, word32); +#endif + void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); + void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } +private: + static const word32 p_init_[ROUNDS + 2]; + static const word32 s_init_[4 * 256]; + + word32 pbox_[ROUNDS + 2 + 4 * 256]; + word32* sbox_; + + void crypt_block(const word32 in[2], word32 out[2]) const; + void AsmProcess(const byte* in, byte* out) const; + void ProcessAndXorBlock(const byte*, const byte*, byte*) const; + + Blowfish(const Blowfish&); // hide copy + Blowfish& operator=(const Blowfish&); // and assign +}; + + +typedef BlockCipher Blowfish_ECB_Encryption; +typedef BlockCipher Blowfish_ECB_Decryption; + +typedef BlockCipher Blowfish_CBC_Encryption; +typedef BlockCipher Blowfish_CBC_Decryption; + + + +} // namespace + +#endif // TAO_CRYPT_BLOWFISH_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/coding.hpp b/mysql/extra/yassl/taocrypt/include/coding.hpp new file mode 100644 index 0000000..61ac993 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/coding.hpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* coding.hpp defines hex and base64 encoding/decoing +*/ + +#ifndef TAO_CRYPT_CODING_HPP +#define TAO_CRYPT_CODING_HPP + +#include "misc.hpp" +#include "block.hpp" + +namespace TaoCrypt { + +class Source; + + +// Hex Encoding, see RFC 3548 +class HexEncoder { + ByteBlock encoded_; + Source& plain_; +public: + explicit HexEncoder(Source& s) : plain_(s) { Encode(); } +private: + void Encode(); + + HexEncoder(const HexEncoder&); // hide copy + HexEncoder& operator=(const HexEncoder&); // and assign +}; + + +// Hex Decoding, see RFC 3548 +class HexDecoder { + ByteBlock decoded_; + Source& coded_; +public: + explicit HexDecoder(Source& s) : coded_(s) { Decode(); } +private: + void Decode(); + + HexDecoder(const HexDecoder&); // hide copy + HexDecoder& operator=(const HexDecoder&); // and assign +}; + + +// Base 64 encoding, see RFC 3548 +class Base64Encoder { + ByteBlock encoded_; + Source& plain_; +public: + explicit Base64Encoder(Source& s) : plain_(s) { Encode(); } +private: + void Encode(); + + Base64Encoder(const Base64Encoder&); // hide copy + Base64Encoder& operator=(const Base64Encoder&); // and assign +}; + + +// Base 64 decoding, see RFC 3548 +class Base64Decoder { + ByteBlock decoded_; + Source& coded_; +public: + explicit Base64Decoder(Source& s) : coded_(s) { Decode(); } +private: + void Decode(); + + Base64Decoder(const Base64Decoder&); // hide copy + Base64Decoder& operator=(const Base64Decoder&); // and assign +}; + + +} // namespace + +#endif // TAO_CRYPT_CODING_HPP diff --git a/mysql/extra/yassl/taocrypt/include/des.hpp b/mysql/extra/yassl/taocrypt/include/des.hpp new file mode 100644 index 0000000..d88e9ef --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/des.hpp @@ -0,0 +1,130 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* des.hpp defines DES, DES_EDE2, and DES_EDE3 + see FIPS 46-2 and FIPS 81 +*/ + + +#ifndef TAO_CRYPT_DES_HPP +#define TAO_CRYPT_DES_HPP + +#include "misc.hpp" +#include "modes.hpp" + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_DES_ASM +#endif + + +namespace TaoCrypt { + + +enum { DES_BLOCK_SIZE = 8, DES_KEY_SIZE = 32 }; + + +class BasicDES { +public: + void SetKey(const byte*, word32, CipherDir dir); + void RawProcessBlock(word32&, word32&) const; +protected: + word32 k_[DES_KEY_SIZE]; +}; + + +// DES +class DES : public Mode_BASE, public BasicDES { +public: + DES(CipherDir DIR, Mode MODE) + : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} + +private: + void ProcessAndXorBlock(const byte*, const byte*, byte*) const; + + DES(const DES&); // hide copy + DES& operator=(const DES&); // and assign +}; + + +// DES_EDE2 +class DES_EDE2 : public Mode_BASE { +public: + DES_EDE2(CipherDir DIR, Mode MODE) + : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} + + void SetKey(const byte*, word32, CipherDir dir); +private: + BasicDES des1_; + BasicDES des2_; + + void ProcessAndXorBlock(const byte*, const byte*, byte*) const; + + DES_EDE2(const DES_EDE2&); // hide copy + DES_EDE2& operator=(const DES_EDE2&); // and assign +}; + + + +// DES_EDE3 +class DES_EDE3 : public Mode_BASE { +public: + DES_EDE3(CipherDir DIR, Mode MODE) + : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} + + void SetKey(const byte*, word32, CipherDir dir); + void SetIV(const byte* iv) { memcpy(r_, iv, DES_BLOCK_SIZE); } +#ifdef DO_DES_ASM + void Process(byte*, const byte*, word32); +#endif +private: + BasicDES des1_; + BasicDES des2_; + BasicDES des3_; + + void AsmProcess(const byte* in, byte* out, void* box) const; + void ProcessAndXorBlock(const byte*, const byte*, byte*) const; + + DES_EDE3(const DES_EDE3&); // hide copy + DES_EDE3& operator=(const DES_EDE3&); // and assign +}; + + +typedef BlockCipher DES_ECB_Encryption; +typedef BlockCipher DES_ECB_Decryption; + +typedef BlockCipher DES_CBC_Encryption; +typedef BlockCipher DES_CBC_Decryption; + +typedef BlockCipher DES_EDE2_ECB_Encryption; +typedef BlockCipher DES_EDE2_ECB_Decryption; + +typedef BlockCipher DES_EDE2_CBC_Encryption; +typedef BlockCipher DES_EDE2_CBC_Decryption; + +typedef BlockCipher DES_EDE3_ECB_Encryption; +typedef BlockCipher DES_EDE3_ECB_Decryption; + +typedef BlockCipher DES_EDE3_CBC_Encryption; +typedef BlockCipher DES_EDE3_CBC_Decryption; + + +} // namespace + + +#endif // TAO_CRYPT_DES_HPP diff --git a/mysql/extra/yassl/taocrypt/include/dh.hpp b/mysql/extra/yassl/taocrypt/include/dh.hpp new file mode 100644 index 0000000..bdb90dd --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/dh.hpp @@ -0,0 +1,86 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* dh.hpp provides Diffie-Hellman support +*/ + + +#ifndef TAO_CRYPT_DH_HPP +#define TAO_CRYPT_DH_HPP + +#include "misc.hpp" +#include "integer.hpp" + +namespace TaoCrypt { + + +class Source; + + +// Diffie-Hellman +class DH { +public: + DH() {} + DH(Integer& p, Integer& g) : p_(p), g_(g) {} + explicit DH(Source&); + + DH(const DH& that) : p_(that.p_), g_(that.g_) {} + DH& operator=(const DH& that) + { + DH tmp(that); + Swap(tmp); + return *this; + } + + void Swap(DH& other) + { + p_.Swap(other.p_); + g_.Swap(other.g_); + } + + void Initialize(Source&); + void Initialize(Integer& p, Integer& g) + { + SetP(p); + SetG(g); + } + + void GenerateKeyPair(RandomNumberGenerator&, byte*, byte*); + void Agree(byte*, const byte*, const byte*, word32 otherSz = 0); + + void SetP(const Integer& p) { p_ = p; } + void SetG(const Integer& g) { g_ = g; } + + Integer& GetP() { return p_; } + Integer& GetG() { return g_; } + + // for p and agree + word32 GetByteLength() const { return p_.ByteCount(); } +private: + // group parms + Integer p_; + Integer g_; + + void GeneratePrivate(RandomNumberGenerator&, byte*); + void GeneratePublic(const byte*, byte*); +}; + + +} // namespace + +#endif // TAO_CRYPT_DH_HPP diff --git a/mysql/extra/yassl/taocrypt/include/dsa.hpp b/mysql/extra/yassl/taocrypt/include/dsa.hpp new file mode 100644 index 0000000..d7f81c2 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/dsa.hpp @@ -0,0 +1,126 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* dsa.hpp provides Digitial Signautre Algorithm see FIPS 186-2 +*/ + +#ifndef TAO_CRYPT_DSA_HPP +#define TAO_CRYPT_DSA_HPP + +#include "integer.hpp" + + +namespace TaoCrypt { + +class Source; + + +class DSA_PublicKey { +protected: + Integer p_; + Integer q_; + Integer g_; + Integer y_; +public: + DSA_PublicKey() {} + explicit DSA_PublicKey(Source&); + + void Initialize(Source&); + void Initialize(const Integer& p, const Integer& q, const Integer& g, + const Integer& y); + + const Integer& GetModulus() const; + const Integer& GetSubGroupOrder() const; + const Integer& GetSubGroupGenerator() const; + const Integer& GetPublicPart() const; + + void SetModulus(const Integer&); + void SetSubGroupOrder(const Integer&); + void SetSubGroupGenerator(const Integer&); + void SetPublicPart(const Integer&); + + word32 SignatureLength() const; + + DSA_PublicKey(const DSA_PublicKey&); + DSA_PublicKey& operator=(const DSA_PublicKey&); + + void Swap(DSA_PublicKey& other); +}; + + + +class DSA_PrivateKey : public DSA_PublicKey { + Integer x_; +public: + DSA_PrivateKey() {} + explicit DSA_PrivateKey(Source&); + + void Initialize(Source&); + void Initialize(const Integer& p, const Integer& q, const Integer& g, + const Integer& y, const Integer& x); + + const Integer& GetPrivatePart() const; + + void SetPrivatePart(const Integer&); +private: + DSA_PrivateKey(const DSA_PrivateKey&); // hide copy + DSA_PrivateKey& operator=(const DSA_PrivateKey&); // and assign +}; + + + +class DSA_Signer { + const DSA_PrivateKey& key_; + Integer r_; + Integer s_; +public: + explicit DSA_Signer(const DSA_PrivateKey&); + + word32 Sign(const byte* sha_digest, byte* sig, RandomNumberGenerator&); + + const Integer& GetR() const; + const Integer& GetS() const; +private: + DSA_Signer(const DSA_Signer&); // hide copy + DSA_Signer& operator=(DSA_Signer&); // and assign +}; + + +class DSA_Verifier { + const DSA_PublicKey& key_; + Integer r_; + Integer s_; +public: + explicit DSA_Verifier(const DSA_PublicKey&); + + bool Verify(const byte* sha_digest, const byte* sig); + + const Integer& GetR() const; + const Integer& GetS() const; +private: + DSA_Verifier(const DSA_Verifier&); // hide copy + DSA_Verifier& operator=(const DSA_Verifier&); // and assign +}; + + + + + +} // namespace + +#endif // TAO_CRYPT_DSA_HPP diff --git a/mysql/extra/yassl/taocrypt/include/error.hpp b/mysql/extra/yassl/taocrypt/include/error.hpp new file mode 100644 index 0000000..cb2130d --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/error.hpp @@ -0,0 +1,88 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* error.hpp provides a taocrypt error numbers + * + */ + + +#ifndef TAO_CRYPT_ERROR_HPP +#define TAO_CRYPT_ERROR_HPP + + +namespace TaoCrypt { + + +enum ErrorNumber { + +NO_ERROR_E = 0, // "not in error state" + +// RandomNumberGenerator +WINCRYPT_E = 1001, // "bad wincrypt acquire" +CRYPTGEN_E = 1002, // "CryptGenRandom error" +OPEN_RAN_E = 1003, // "open /dev/urandom error" +READ_RAN_E = 1004, // "read /dev/urandom error" + +// Integer +INTEGER_E = 1010, // "bad DER Integer Header" + + +// ASN.1 +SEQUENCE_E = 1020, // "bad Sequence Header" +SET_E = 1021, // "bad Set Header" +VERSION_E = 1022, // "version length not 1" +SIG_OID_E = 1023, // "signature OID mismatch" +BIT_STR_E = 1024, // "bad BitString Header" +UNKNOWN_OID_E = 1025, // "unknown key OID type" +OBJECT_ID_E = 1026, // "bad Ojbect ID Header" +TAG_NULL_E = 1027, // "expected TAG NULL" +EXPECT_0_E = 1028, // "expected 0" +OCTET_STR_E = 1029, // "bad Octet String Header" +TIME_E = 1030, // "bad TIME" + +DATE_SZ_E = 1031, // "bad Date Size" +SIG_LEN_E = 1032, // "bad Signature Length" +UNKOWN_SIG_E = 1033, // "unknown signature OID" +UNKOWN_HASH_E = 1034, // "unknown hash OID" +DSA_SZ_E = 1035, // "bad DSA r or s size" +BEFORE_DATE_E = 1036, // "before date in the future" +AFTER_DATE_E = 1037, // "after date in the past" +SIG_CONFIRM_E = 1038, // "bad self signature confirmation" +SIG_OTHER_E = 1039, // "bad other signature confirmation" + +CONTENT_E = 1040, // "bad content processing" +PEM_E = 1041 // "bad pem format error" + + // add error string to yassl/src/yassl_error.cpp !!! +}; + + +struct Error { + ErrorNumber what_; // description number, 0 for no error + + explicit Error(ErrorNumber w = NO_ERROR_E) : what_(w) {} + + ErrorNumber What() const { return what_; } + void SetError(ErrorNumber w) { what_ = w; } +}; + + + +} // namespace TaoCrypt + +#endif // TAO_CRYPT_ERROR_HPP diff --git a/mysql/extra/yassl/taocrypt/include/file.hpp b/mysql/extra/yassl/taocrypt/include/file.hpp new file mode 100644 index 0000000..9851a00 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/file.hpp @@ -0,0 +1,130 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* file.hpp provies File Sources and Sinks +*/ + + +#ifndef TAO_CRYPT_FILE_HPP +#define TAO_CRYPT_FILE_HPP + +#include "misc.hpp" +#include "block.hpp" +#include "error.hpp" +#include + +namespace TaoCrypt { + + +class Source { + ByteBlock buffer_; + word32 current_; + Error error_; +public: + explicit Source(word32 sz = 0) : buffer_(sz), current_(0) {} + Source(const byte* b, word32 sz) : buffer_(b, sz), current_(0) {} + + word32 remaining() { if (GetError().What()) return 0; + else return buffer_.size() - current_; } + word32 size() const { return buffer_.size(); } + void grow(word32 sz) { buffer_.CleanGrow(sz); } + + bool IsLeft(word32 sz) { if (remaining() >= sz) return true; + else { SetError(CONTENT_E); return false; } } + + const byte* get_buffer() const { return buffer_.get_buffer(); } + const byte* get_current() const { return &buffer_[current_]; } + word32 get_index() const { return current_; } + void set_index(word32 i) { if (i < size()) current_ = i; } + + byte operator[] (word32 i) { current_ = i; return next(); } + byte next() { if (IsLeft(1)) return buffer_[current_++]; else return 0; } + byte prev() { if (current_) return buffer_[--current_]; else return 0; } + + void add(const byte* data, word32 len) + { + if (IsLeft(len)) { + memcpy(buffer_.get_buffer() + current_, data, len); + current_ += len; + } + } + + void advance(word32 i) { if (IsLeft(i)) current_ += i; } + void reset(ByteBlock&); + + Error GetError() { return error_; } + void SetError(ErrorNumber w) { error_.SetError(w); } + + friend class FileSource; // for get() + + Source(const Source& that) + : buffer_(that.buffer_), current_(that.current_) {} + + Source& operator=(const Source& that) + { + Source tmp(that); + Swap(tmp); + return *this; + } + + void Swap(Source& other) + { + buffer_.Swap(other.buffer_); + STL::swap(current_, other.current_); + } + +}; + + +// File Source +class FileSource { + FILE* file_; +public: + FileSource(const char* fname, Source& source); + ~FileSource(); + + word32 size(bool use_current = false); +private: + word32 get(Source&); + word32 size_left(); + + FileSource(const FileSource&); // hide + FileSource& operator=(const FileSource&); // hide +}; + + +// File Sink +class FileSink { + FILE* file_; +public: + FileSink(const char* fname, Source& source); + ~FileSink(); + + word32 size(bool use_current = false); +private: + void put(Source&); + + FileSink(const FileSink&); // hide + FileSink& operator=(const FileSink&); // hide +}; + + + +} // namespace + +#endif // TAO_CRYPT_FILE_HPP diff --git a/mysql/extra/yassl/taocrypt/include/hash.hpp b/mysql/extra/yassl/taocrypt/include/hash.hpp new file mode 100644 index 0000000..4d2f7dd --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/hash.hpp @@ -0,0 +1,110 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* hash.hpp provides a base for digest types +*/ + + +#ifndef TAO_CRYPT_HASH_HPP +#define TAO_CRYPT_HASH_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +// HASH +class HASH : public virtual_base { +public: + virtual ~HASH() {} + + virtual void Update(const byte*, word32) = 0; + virtual void Final(byte*) = 0; + + virtual void Init() = 0; + + virtual word32 getBlockSize() const = 0; + virtual word32 getDigestSize() const = 0; +}; + + +// HASH with Transform +class HASHwithTransform : public HASH { +public: + HASHwithTransform(word32 digSz, word32 buffSz); + virtual ~HASHwithTransform() {} + virtual ByteOrder getByteOrder() const = 0; + virtual word32 getPadSize() const = 0; + + virtual void Update(const byte*, word32); + virtual void Final(byte*); + + word32 GetBitCountLo() const { return loLen_ << 3; } + word32 GetBitCountHi() const { return (loLen_ >> (8*sizeof(loLen_) - 3)) + + (hiLen_ << 3); } + enum { MaxDigestSz = 8, MaxBufferSz = 64 }; +protected: + typedef word32 HashLengthType; + word32 buffLen_; // in bytes + HashLengthType loLen_; // length in bytes + HashLengthType hiLen_; // length in bytes + word32 digest_[MaxDigestSz]; + word32 buffer_[MaxBufferSz / sizeof(word32)]; + + virtual void Transform() = 0; + + void AddLength(word32); +}; + + +#ifdef WORD64_AVAILABLE + +// 64-bit HASH with Transform +class HASH64withTransform : public HASH { +public: + HASH64withTransform(word32 digSz, word32 buffSz); + virtual ~HASH64withTransform() {} + virtual ByteOrder getByteOrder() const = 0; + virtual word32 getPadSize() const = 0; + + virtual void Update(const byte*, word32); + virtual void Final(byte*); + + word32 GetBitCountLo() const { return loLen_ << 3; } + word32 GetBitCountHi() const { return (loLen_ >> (8*sizeof(loLen_) - 3)) + + (hiLen_ << 3); } + enum { MaxDigestSz = 8, MaxBufferSz = 128 }; +protected: + typedef word32 HashLengthType; + word32 buffLen_; // in bytes + HashLengthType loLen_; // length in bytes + HashLengthType hiLen_; // length in bytes + word64 digest_[MaxDigestSz]; + word64 buffer_[MaxBufferSz / sizeof(word64)]; + + virtual void Transform() = 0; + + void AddLength(word32); +}; + +#endif // WORD64_AVAILABLE + + +} // namespace + +#endif // TAO_CRYPT_HASH_HPP diff --git a/mysql/extra/yassl/taocrypt/include/hc128.hpp b/mysql/extra/yassl/taocrypt/include/hc128.hpp new file mode 100644 index 0000000..69e9d63 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/hc128.hpp @@ -0,0 +1,63 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* hc128.hpp defines HC128 +*/ + + +#ifndef TAO_CRYPT_HC128_HPP +#define TAO_CRYPT_HC128_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +// HC128 encryption and decryption +class HC128 { +public: + + typedef HC128 Encryption; + typedef HC128 Decryption; + + + HC128() {} + + void Process(byte*, const byte*, word32); + void SetKey(const byte*, const byte*); +private: + word32 T_[1024]; /* P[i] = T[i]; Q[i] = T[1024 + i ]; */ + word32 X_[16]; + word32 Y_[16]; + word32 counter1024_; /* counter1024 = i mod 1024 at the ith step */ + word32 key_[8]; + word32 iv_[8]; + + void SetIV(const byte*); + void GenerateKeystream(word32*); + void SetupUpdate(); + + HC128(const HC128&); // hide copy + const HC128 operator=(const HC128&); // and assign +}; + +} // namespace + + +#endif // TAO_CRYPT_HC128_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/hmac.hpp b/mysql/extra/yassl/taocrypt/include/hmac.hpp new file mode 100644 index 0000000..4df081b --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/hmac.hpp @@ -0,0 +1,138 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* hamc.hpp implements HMAC, see RFC 2104 +*/ + + +#ifndef TAO_CRYPT_HMAC_HPP +#define TAO_CRYPT_HMAC_HPP + +#include "hash.hpp" + +namespace TaoCrypt { + + +// HMAC class template +template +class HMAC { +public: + enum { IPAD = 0x36, OPAD = 0x5C }; + + HMAC() : ipad_(reinterpret_cast(&ip_)), + opad_(reinterpret_cast(&op_)), + innerHash_(reinterpret_cast(&innerH_)) + { + Init(); + } + void Update(const byte*, word32); + void Final(byte*); + void Init(); + + void SetKey(const byte*, word32); +private: + byte* ipad_; + byte* opad_; + byte* innerHash_; + bool innerHashKeyed_; + T mac_; + + // MSVC 6 HACK, gives compiler error if calculated in array + enum { HMAC_BSIZE = T::BLOCK_SIZE / sizeof(word32), + HMAC_DSIZE = T::DIGEST_SIZE / sizeof(word32) }; + + word32 ip_[HMAC_BSIZE]; // align ipad_ on word32 + word32 op_[HMAC_BSIZE]; // align opad_ on word32 + word32 innerH_[HMAC_DSIZE]; // align innerHash_ on word32 + + void KeyInnerHash(); + + HMAC(const HMAC&); + HMAC& operator= (const HMAC&); +}; + + +// Setup +template +void HMAC::Init() +{ + mac_.Init(); + innerHashKeyed_ = false; +} + + +// Key generation +template +void HMAC::SetKey(const byte* key, word32 length) +{ + Init(); + + if (length <= T::BLOCK_SIZE) + memcpy(ipad_, key, length); + else { + mac_.Update(key, length); + mac_.Final(ipad_); + length = T::DIGEST_SIZE; + } + memset(ipad_ + length, 0, T::BLOCK_SIZE - length); + + for (word32 i = 0; i < T::BLOCK_SIZE; i++) { + opad_[i] = ipad_[i] ^ OPAD; + ipad_[i] ^= IPAD; + } +} + + +// Inner Key Hash +template +void HMAC::KeyInnerHash() +{ + mac_.Update(ipad_, T::BLOCK_SIZE); + innerHashKeyed_ = true; +} + + +// Update +template +void HMAC::Update(const byte* msg, word32 length) +{ + if (!innerHashKeyed_) + KeyInnerHash(); + mac_.Update(msg, length); +} + + +// Final +template +void HMAC::Final(byte* hash) +{ + if (!innerHashKeyed_) + KeyInnerHash(); + mac_.Final(innerHash_); + + mac_.Update(opad_, T::BLOCK_SIZE); + mac_.Update(innerHash_, T::DIGEST_SIZE); + mac_.Final(hash); + + innerHashKeyed_ = false; +} + + +} // namespace + +#endif // TAO_CRYPT_HMAC_HPP diff --git a/mysql/extra/yassl/taocrypt/include/integer.hpp b/mysql/extra/yassl/taocrypt/include/integer.hpp new file mode 100644 index 0000000..05fe189 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/integer.hpp @@ -0,0 +1,332 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's integer.h from CryptoPP */ + + +#ifndef TAO_CRYPT_INTEGER_HPP +#define TAO_CRYPT_INTEGER_HPP + + +#ifdef _MSC_VER + // 4250: dominance + // 4660: explicitly instantiating a class already implicitly instantiated + // 4661: no suitable definition provided for explicit template request + // 4786: identifer was truncated in debug information + // 4355: 'this' : used in base member initializer list +# pragma warning(disable: 4250 4660 4661 4786 4355) +#endif + + +#include "misc.hpp" +#include "block.hpp" +#include "random.hpp" +#include "file.hpp" +#include +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + #if defined(__GNUC__) && (__GNUC__ >= 4) + // GCC 4 or greater optimizes too much inline on recursive for bigint, + // -O3 just as fast without asm here anyway + #undef TAOCRYPT_X86ASM_AVAILABLE + #endif +#endif + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + +#ifdef _M_IX86 + #if (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)) || \ + (defined(__ICL) && (__ICL >= 500)) + #define SSE2_INTRINSICS_AVAILABLE + #define TAOCRYPT_MM_MALLOC_AVAILABLE + #elif defined(_MSC_VER) + // _mm_free seems to be the only way to tell if the Processor Pack is + //installed or not + #include + #if defined(_mm_free) + #define SSE2_INTRINSICS_AVAILABLE + #define TAOCRYPT_MM_MALLOC_AVAILABLE + #endif + #endif +#endif + +// SSE2 intrinsics work in GCC 3.3 or later +#if defined(__SSE2__) && (__GNUC__ == 4 || __GNUC_MAJOR__ > 3 || \ + __GNUC_MINOR__ > 2) + #define SSE2_INTRINSICS_AVAILABLE +#endif + +#endif // X86ASM + + + + +namespace TaoCrypt { + +#if defined(SSE2_INTRINSICS_AVAILABLE) + + // Allocator handling proper alignment + template + class AlignedAllocator : public AllocatorBase + { + public: + typedef typename AllocatorBase::pointer pointer; + typedef typename AllocatorBase::size_type size_type; + + pointer allocate(size_type n, const void* = 0); + void deallocate(void* p, size_type n); + pointer reallocate(T* p, size_type oldSize, size_type newSize, + bool preserve) + { + return StdReallocate(*this, p, oldSize, newSize, preserve); + } + + #if !(defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16) || \ + defined(TAOCRYPT_MEMALIGN_AVAILABLE) || \ + defined(TAOCRYPT_MM_MALLOC_AVAILABLE)) + #define TAOCRYPT_NO_ALIGNED_ALLOC + AlignedAllocator() : m_pBlock(0) {} + protected: + void *m_pBlock; + #endif + }; + + typedef Block > AlignedWordBlock; +#else + typedef WordBlock AlignedWordBlock; +#endif + + + +#ifdef _WIN32 + #undef max // avoid name clash +#endif +// general MAX +template inline +const T& max(const T& a, const T& b) +{ + return a > b ? a : b; +} + + +// Large Integer class +class Integer { +public: + enum Sign {POSITIVE = 0, NEGATIVE = 1 }; + enum Signedness { UNSIGNED, SIGNED }; + enum RandomNumberType { ANY, PRIME }; + + class DivideByZero {}; + + Integer(); + Integer(const Integer& t); + Integer(signed long value); + Integer(Sign s, word highWord, word lowWord); + + // BER Decode Source + explicit Integer(Source&); + + Integer(const byte* encodedInteger, unsigned int byteCount, + Signedness s = UNSIGNED); + + ~Integer() {} + + static const Integer& Zero(); + static const Integer& One(); + + Integer& Ref() { return *this; } + + Integer(RandomNumberGenerator& rng, const Integer& min, + const Integer& max); + + static Integer Power2(unsigned int e); + + unsigned int MinEncodedSize(Signedness = UNSIGNED) const; + unsigned int Encode(byte* output, unsigned int outputLen, + Signedness = UNSIGNED) const; + + void Decode(const byte* input, unsigned int inputLen, + Signedness = UNSIGNED); + void Decode(Source&); + + bool IsConvertableToLong() const; + signed long ConvertToLong() const; + + unsigned int BitCount() const; + unsigned int ByteCount() const; + unsigned int WordCount() const; + + bool GetBit(unsigned int i) const; + byte GetByte(unsigned int i) const; + unsigned long GetBits(unsigned int i, unsigned int n) const; + + bool IsZero() const { return !*this; } + bool NotZero() const { return !IsZero(); } + bool IsNegative() const { return sign_ == NEGATIVE; } + bool NotNegative() const { return !IsNegative(); } + bool IsPositive() const { return NotNegative() && NotZero(); } + bool NotPositive() const { return !IsPositive(); } + bool IsEven() const { return GetBit(0) == 0; } + bool IsOdd() const { return GetBit(0) == 1; } + + Integer& operator=(const Integer& t); + Integer& operator+=(const Integer& t); + Integer& operator-=(const Integer& t); + Integer& operator*=(const Integer& t) { return *this = Times(t); } + Integer& operator/=(const Integer& t) + { return *this = DividedBy(t);} + Integer& operator%=(const Integer& t) { return *this = Modulo(t); } + Integer& operator/=(word t) { return *this = DividedBy(t); } + Integer& operator%=(word t) { return *this = Modulo(t); } + Integer& operator<<=(unsigned int); + Integer& operator>>=(unsigned int); + + + void Randomize(RandomNumberGenerator &rng, unsigned int bitcount); + void Randomize(RandomNumberGenerator &rng, const Integer &min, + const Integer &max); + + void SetBit(unsigned int n, bool value = 1); + void SetByte(unsigned int n, byte value); + + void Negate(); + void SetPositive() { sign_ = POSITIVE; } + void SetNegative() { if (!!(*this)) sign_ = NEGATIVE; } + void Swap(Integer& a); + + bool operator!() const; + Integer operator+() const {return *this;} + Integer operator-() const; + Integer& operator++(); + Integer& operator--(); + Integer operator++(int) + { Integer temp = *this; ++*this; return temp; } + Integer operator--(int) + { Integer temp = *this; --*this; return temp; } + + int Compare(const Integer& a) const; + + Integer Plus(const Integer &b) const; + Integer Minus(const Integer &b) const; + Integer Times(const Integer &b) const; + Integer DividedBy(const Integer &b) const; + Integer Modulo(const Integer &b) const; + Integer DividedBy(word b) const; + word Modulo(word b) const; + + Integer operator>>(unsigned int n) const { return Integer(*this)>>=n; } + Integer operator<<(unsigned int n) const { return Integer(*this)<<=n; } + + Integer AbsoluteValue() const; + Integer Doubled() const { return Plus(*this); } + Integer Squared() const { return Times(*this); } + Integer SquareRoot() const; + + bool IsSquare() const; + bool IsUnit() const; + + Integer MultiplicativeInverse() const; + + friend Integer a_times_b_mod_c(const Integer& x, const Integer& y, + const Integer& m); + friend Integer a_exp_b_mod_c(const Integer& x, const Integer& e, + const Integer& m); + + static void Divide(Integer& r, Integer& q, const Integer& a, + const Integer& d); + static void Divide(word& r, Integer& q, const Integer& a, word d); + static void DivideByPowerOf2(Integer& r, Integer& q, const Integer& a, + unsigned int n); + static Integer Gcd(const Integer& a, const Integer& n); + + Integer InverseMod(const Integer& n) const; + word InverseMod(word n) const; + +private: + friend class ModularArithmetic; + friend class MontgomeryRepresentation; + + Integer(word value, unsigned int length); + int PositiveCompare(const Integer& t) const; + + friend void PositiveAdd(Integer& sum, const Integer& a, const Integer& b); + friend void PositiveSubtract(Integer& diff, const Integer& a, + const Integer& b); + friend void PositiveMultiply(Integer& product, const Integer& a, + const Integer& b); + friend void PositiveDivide(Integer& remainder, Integer& quotient, const + Integer& dividend, const Integer& divisor); + AlignedWordBlock reg_; + Sign sign_; +}; + +inline bool operator==(const Integer& a, const Integer& b) + {return a.Compare(b)==0;} +inline bool operator!=(const Integer& a, const Integer& b) + {return a.Compare(b)!=0;} +inline bool operator> (const Integer& a, const Integer& b) + {return a.Compare(b)> 0;} +inline bool operator>=(const Integer& a, const Integer& b) + {return a.Compare(b)>=0;} +inline bool operator< (const Integer& a, const Integer& b) + {return a.Compare(b)< 0;} +inline bool operator<=(const Integer& a, const Integer& b) + {return a.Compare(b)<=0;} + +inline Integer operator+(const Integer &a, const Integer &b) + {return a.Plus(b);} +inline Integer operator-(const Integer &a, const Integer &b) + {return a.Minus(b);} +inline Integer operator*(const Integer &a, const Integer &b) + {return a.Times(b);} +inline Integer operator/(const Integer &a, const Integer &b) + {return a.DividedBy(b);} +inline Integer operator%(const Integer &a, const Integer &b) + {return a.Modulo(b);} +inline Integer operator/(const Integer &a, word b) {return a.DividedBy(b);} +inline word operator%(const Integer &a, word b) {return a.Modulo(b);} + +inline void swap(Integer &a, Integer &b) +{ + a.Swap(b); +} + + +Integer CRT(const Integer& xp, const Integer& p, const Integer& xq, + const Integer& q, const Integer& u); + +inline Integer ModularExponentiation(const Integer& a, const Integer& e, + const Integer& m) +{ + return a_exp_b_mod_c(a, e, m); +} + +Integer ModularRoot(const Integer& a, const Integer& dp, const Integer& dq, + const Integer& p, const Integer& q, const Integer& u); + + + +} // namespace + +#endif // TAO_CRYPT_INTEGER_HPP diff --git a/mysql/extra/yassl/taocrypt/include/kernelc.hpp b/mysql/extra/yassl/taocrypt/include/kernelc.hpp new file mode 100644 index 0000000..0840b3f --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/kernelc.hpp @@ -0,0 +1,34 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* kernelc.hpp provides support for C std lib when compiled in kernel mode +*/ + +#ifndef TAOCRYPT_KERNELC_HPP +#define TAOCRYPT_KERNELC_HPP + +#include // get right size_t + +// system functions that c++ doesn't like headers for + +extern "C" void* memcpy(void*, const void*, size_t); +extern "C" void* memset(void*, int, size_t); +extern "C" void printk(char *fmt, ...); + + +#endif // TAOCRYPT_KERNELC_HPP diff --git a/mysql/extra/yassl/taocrypt/include/md2.hpp b/mysql/extra/yassl/taocrypt/include/md2.hpp new file mode 100644 index 0000000..5c2b141 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/md2.hpp @@ -0,0 +1,64 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* md2.hpp provides MD2 digest support, see RFC 1319 +*/ + +#ifndef TAO_CRYPT_MD2_HPP +#define TAO_CRYPT_MD2_HPP + + +#include "hash.hpp" +#include "block.hpp" + + +namespace TaoCrypt { + + +// MD2 digest +class MD2 : public HASH { +public: + enum { BLOCK_SIZE = 16, DIGEST_SIZE = 16, PAD_SIZE = 16, X_SIZE = 48 }; + MD2(); + + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + + void Update(const byte*, word32); + void Final(byte*); + + void Init(); + void Swap(MD2&); +private: + ByteBlock X_, C_, buffer_; + word32 count_; // bytes % PAD_SIZE + + MD2(const MD2&); + MD2& operator=(const MD2&); +}; + +inline void swap(MD2& a, MD2& b) +{ + a.Swap(b); +} + + +} // namespace + +#endif // TAO_CRYPT_MD2_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/md4.hpp b/mysql/extra/yassl/taocrypt/include/md4.hpp new file mode 100644 index 0000000..424c744 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/md4.hpp @@ -0,0 +1,62 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* md4.hpp provides MD4 digest support + * WANRING: MD4 is considered insecure, only use if you have to, e.g., yaSSL + * libcurl supports needs this for NTLM authentication +*/ + +#ifndef TAO_CRYPT_MD4_HPP +#define TAO_CRYPT_MD4_HPP + +#include "hash.hpp" + +namespace TaoCrypt { + + +// MD4 digest +class MD4 : public HASHwithTransform { +public: + enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56, + TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes + MD4() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + MD4(const MD4&); + MD4& operator= (const MD4&); + + void Init(); + void Swap(MD4&); +private: + void Transform(); +}; + +inline void swap(MD4& a, MD4& b) +{ + a.Swap(b); +} + + +} // namespace + +#endif // TAO_CRYPT_MD4_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/md5.hpp b/mysql/extra/yassl/taocrypt/include/md5.hpp new file mode 100644 index 0000000..fce37bd --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/md5.hpp @@ -0,0 +1,70 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* md5.hpp provides MD5 digest support, see RFC 1321 +*/ + +#ifndef TAO_CRYPT_MD5_HPP +#define TAO_CRYPT_MD5_HPP + +#include "hash.hpp" + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_MD5_ASM +#endif + +namespace TaoCrypt { + + +// MD5 digest +class MD5 : public HASHwithTransform { +public: + enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56, + TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes + MD5() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + MD5(const MD5&); + MD5& operator= (const MD5&); + +#ifdef DO_MD5_ASM + void Update(const byte*, word32); +#endif + + void Init(); + void Swap(MD5&); +private: + void Transform(); + void AsmTransform(const byte* data, word32 times); +}; + +inline void swap(MD5& a, MD5& b) +{ + a.Swap(b); +} + + +} // namespace + +#endif // TAO_CRYPT_MD5_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/misc.hpp b/mysql/extra/yassl/taocrypt/include/misc.hpp new file mode 100644 index 0000000..18f13e7 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/misc.hpp @@ -0,0 +1,888 @@ +/* + Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's misc.h from CryptoPP */ + +#ifndef TAO_CRYPT_MISC_HPP +#define TAO_CRYPT_MISC_HPP + + +#if !defined(DO_TAOCRYPT_KERNEL_MODE) + #include + #include +#else + #include "kernelc.hpp" +#endif + +#include "types.hpp" +#include "type_traits.hpp" + + + +namespace TaoCrypt { + + +// Delete static singleton holders +void CleanUp(); + + +#ifdef YASSL_PURE_C + + // library allocation + struct new_t {}; // TaoCrypt New type + extern new_t tc; // pass in parameter + + } // namespace TaoCrypt + + void* operator new (size_t, TaoCrypt::new_t); + void* operator new[](size_t, TaoCrypt::new_t); + + void operator delete (void*, TaoCrypt::new_t); + void operator delete[](void*, TaoCrypt::new_t); + + + namespace TaoCrypt { + + template + void tcDelete(T* ptr) + { + if (ptr) ptr->~T(); + ::operator delete(ptr, TaoCrypt::tc); + } + + template + void tcArrayDelete(T* ptr) + { + // can't do array placement destruction since not tracking size in + // allocation, only allow builtins to use array placement since they + // don't need destructors called + typedef char builtin[IsFundamentalType::Yes ? 1 : -1]; + (void)sizeof(builtin); + + ::operator delete[](ptr, TaoCrypt::tc); + } + + #define NEW_TC new (TaoCrypt::tc) + + + // to resolve compiler generated operator delete on base classes with + // virtual destructors (when on stack) + class virtual_base { + public: + static void operator delete(void*) { } + }; + +#else // YASSL_PURE_C + + + template + void tcDelete(T* ptr) + { + delete ptr; + } + + template + void tcArrayDelete(T* ptr) + { + delete[] ptr; + } + + #define NEW_TC new + + class virtual_base {}; + + +#endif // YASSL_PURE_C + + +#if defined(_MSC_VER) || defined(__BCPLUSPLUS__) + #define INTEL_INTRINSICS + #define FAST_ROTATE +#elif defined(__MWERKS__) && TARGET_CPU_PPC + #define PPC_INTRINSICS + #define FAST_ROTATE +#elif defined(__GNUC__) && defined(__i386__) + // GCC does peephole optimizations which should result in using rotate + // instructions + #define FAST_ROTATE +#endif + + +// no gas on these systems ?, disable for now +#if defined(__sun__) + #undef TAOCRYPT_DISABLE_X86ASM + #define TAOCRYPT_DISABLE_X86ASM +#endif + +// icc problem with -03 and integer, disable for now +#if defined(__INTEL_COMPILER) + #undef TAOCRYPT_DISABLE_X86ASM + #define TAOCRYPT_DISABLE_X86ASM +#endif + +// indpedent of build system, unless ia32 asm is enabled disable it +#if !defined(TAOCRYPT_ENABLE_X86ASM) + #undef TAOCRYPT_DISABLE_X86ASM + #define TAOCRYPT_DISABLE_X86ASM +#endif + +// Turn on ia32 ASM for Big Integer +// CodeWarrior defines _MSC_VER +#if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \ + !defined(__MWERKS__) && defined(_M_IX86)) || \ + (defined(__GNUC__) && defined(__i386__))) + #define TAOCRYPT_X86ASM_AVAILABLE +#endif + + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + bool HaveCpuId(); + bool IsPentium(); + void CpuId(word32 input, word32 *output); + + extern bool isMMX; +#endif + + + + +// Turn on ia32 ASM for Ciphers and Message Digests +// Seperate define since these are more complex, use member offsets +// and user may want to turn off while leaving Big Integer optos on +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && !defined(DISABLE_TAO_ASM) + #define TAO_ASM +#endif + + +// Extra word in older vtable implementations, for ASM member offset +#if defined(__GNUC__) && __GNUC__ < 3 + #define OLD_GCC_OFFSET +#endif + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# define TAOCRYPT_MALLOC_ALIGNMENT_IS_16 +#endif + +#if defined(__linux__) || defined(__sun__) +# define TAOCRYPT_MEMALIGN_AVAILABLE +#endif + + +#if defined(_WIN32) + #define TAOCRYPT_WIN32_AVAILABLE +#endif + +#if defined(__unix__) || defined(__MACH__) + #define TAOCRYPT_UNIX_AVAILABLE +#endif + + +// VC60 workaround: it doesn't allow typename in some places +#if defined(_MSC_VER) && (_MSC_VER < 1300) + #define CPP_TYPENAME +#else + #define CPP_TYPENAME typename +#endif + + +#ifdef _MSC_VER + #define TAOCRYPT_NO_VTABLE __declspec(novtable) +#else + #define TAOCRYPT_NO_VTABLE +#endif + + +#ifdef USE_SYS_STL + // use system STL + #define STL_NAMESPACE std +#else + // use mySTL + #define STL_NAMESPACE mySTL +#endif + + +// ***************** DLL related ******************** + +#ifdef TAOCRYPT_WIN32_AVAILABLE + +#ifdef TAOCRYPT_EXPORTS + #define TAOCRYPT_IS_DLL + #define TAOCRYPT_DLL __declspec(dllexport) +#elif defined(TAOCRYPT_IMPORTS) + #define TAOCRYPT_IS_DLL + #define TAOCRYPT_DLL __declspec(dllimport) +#else + #define TAOCRYPT_DLL +#endif // EXPORTS + +#define TAOCRYPT_API __stdcall +#define TAOCRYPT_CDECL __cdecl + +#else // TAOCRYPT_WIN32_AVAILABLE + +#define TAOCRYPT_DLL +#define TAOCRYPT_API +#define TAOCRYPT_CDECL + +#endif // TAOCRYPT_WIN32_AVAILABLE + + +// ****************** tempalte stuff ******************* + + +#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \ + !defined(TAOCRYPT_IMPORTS) + #define TAOCRYPT_DLL_TEMPLATE_CLASS template class TAOCRYPT_DLL +#elif defined(__MWERKS__) + #define TAOCRYPT_DLL_TEMPLATE_CLASS extern class TAOCRYPT_DLL +#else + #define TAOCRYPT_DLL_TEMPLATE_CLASS extern template class TAOCRYPT_DLL +#endif + + +#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \ + !defined(TAOCRYPT_EXPORTS) + #define TAOCRYPT_STATIC_TEMPLATE_CLASS template class +#elif defined(__MWERKS__) + #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern class +#else + #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern template class +#endif + + +// ************** compile-time assertion *************** + +template +struct CompileAssert +{ + static char dummy[2*b-1]; +}; + +#define TAOCRYPT_COMPILE_ASSERT(assertion) \ + TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, __LINE__) + +#if defined(TAOCRYPT_EXPORTS) || defined(TAOCRYPT_IMPORTS) + #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance) +#else + #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance) \ + (void)sizeof(CompileAssert<(assertion)>) +#endif + +#define TAOCRYPT_ASSERT_JOIN(X, Y) TAOCRYPT_DO_ASSERT_JOIN(X, Y) + +#define TAOCRYPT_DO_ASSERT_JOIN(X, Y) X##Y + + +/*************** helpers *****************************/ + +inline unsigned int BitsToBytes(unsigned int bitCount) +{ + return ((bitCount+7)/(8)); +} + +inline unsigned int BytesToWords(unsigned int byteCount) +{ + return ((byteCount+WORD_SIZE-1)/WORD_SIZE); +} + +inline unsigned int BitsToWords(unsigned int bitCount) +{ + return ((bitCount+WORD_BITS-1)/(WORD_BITS)); +} + +inline void CopyWords(word* r, const word* a, word32 n) +{ + for (word32 i = 0; i < n; i++) + r[i] = a[i]; +} + +inline unsigned int CountWords(const word* X, unsigned int N) +{ + while (N && X[N-1]==0) + N--; + return N; +} + +inline void SetWords(word* r, word a, unsigned int n) +{ + for (unsigned int i=0; i +struct EnumToType +{ + static ENUM_TYPE ToEnum() { return (ENUM_TYPE)VALUE; } +}; + +typedef EnumToType LittleEndian; +typedef EnumToType BigEndian; + + +#ifndef BIG_ENDIAN_ORDER + typedef LittleEndian HostByteOrder; +#else + typedef BigEndian HostByteOrder; +#endif + +inline ByteOrder GetHostByteOrder() +{ + return HostByteOrder::ToEnum(); +} + +inline bool HostByteOrderIs(ByteOrder order) +{ + return order == GetHostByteOrder(); +} + + +void xorbuf(byte*, const byte*, unsigned int); + + +template +inline bool IsPowerOf2(T n) +{ + return n > 0 && (n & (n-1)) == 0; +} + +template +inline T2 ModPowerOf2(T1 a, T2 b) +{ + return T2(a) & (b-1); +} + +template +inline T RoundDownToMultipleOf(T n, T m) +{ + return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m)); +} + +template +inline T RoundUpToMultipleOf(T n, T m) +{ + return RoundDownToMultipleOf(n+m-1, m); +} + +template +inline unsigned int GetAlignment(T* dummy = 0) // VC60 workaround +{ +#if (_MSC_VER >= 1300) + return __alignof(T); +#elif defined(__GNUC__) + return __alignof__(T); +#else + return sizeof(T); +#endif +} + +inline bool IsAlignedOn(const void* p, unsigned int alignment) +{ + return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 + : (size_t)p % alignment == 0; +} + +template +inline bool IsAligned(const void* p, T* dummy = 0) // VC60 workaround +{ + return IsAlignedOn(p, GetAlignment()); +} + + +template inline T rotlFixed(T x, unsigned int y) +{ + return (x<>(sizeof(T)*8-y)); +} + +template inline T rotrFixed(T x, unsigned int y) +{ + return (x>>y) | (x<<(sizeof(T)*8-y)); +} + +#ifdef INTEL_INTRINSICS + +#pragma intrinsic(_lrotl, _lrotr) + +template<> inline word32 rotlFixed(word32 x, word32 y) +{ + return y ? _lrotl(x, y) : x; +} + +template<> inline word32 rotrFixed(word32 x, word32 y) +{ + return y ? _lrotr(x, y) : x; +} + +#endif // INTEL_INTRINSICS + +#ifdef min +#undef min +#endif + + +template +inline const T& min(const T& a, const T& b) +{ + return a < b ? a : b; +} + + +inline word32 ByteReverse(word32 value) +{ +#ifdef PPC_INTRINSICS + // PPC: load reverse indexed instruction + return (word32)__lwbrx(&value,0); +#elif defined(FAST_ROTATE) + // 5 instructions with rotate instruction, 9 without + return (rotrFixed(value, 8U) & 0xff00ff00) | + (rotlFixed(value, 8U) & 0x00ff00ff); +#else + // 6 instructions with rotate instruction, 8 without + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return rotlFixed(value, 16U); +#endif +} + + +#ifdef WORD64_AVAILABLE + +inline word64 ByteReverse(word64 value) +{ +#ifdef TAOCRYPT_SLOW_WORD64 + return (word64(ByteReverse(word32(value))) << 32) | + ByteReverse(word32(value>>32)); +#else + value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | + ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); + value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | + ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); + return rotlFixed(value, 32U); +#endif +} + +#endif // WORD64_AVAILABLE + + +template +inline void ByteReverse(T* out, const T* in, word32 byteCount) +{ + word32 count = byteCount/sizeof(T); + for (word32 i=0; i(out); + const word32* i = reinterpret_cast(in); + ByteReverse(o, i, byteCount); +} + + +template +inline T ByteReverseIf(T value, ByteOrder order) +{ + return HostByteOrderIs(order) ? value : ByteReverse(value); +} + + +template +inline void ByteReverseIf(T* out, const T* in, word32 bc, ByteOrder order) +{ + if (!HostByteOrderIs(order)) + ByteReverse(out, in, bc); + else if (out != in) + memcpy(out, in, bc); +} + + + +// do Asm Reverse is host is Little and x86asm +#ifdef LITTLE_ENDIAN_ORDER + #ifdef TAOCRYPT_X86ASM_AVAILABLE + #define LittleReverse AsmReverse + #else + #define LittleReverse ByteReverse + #endif +#else + #define LittleReverse +#endif + + +// do Asm Reverse is host is Big and x86asm +#ifdef BIG_ENDIAN_ORDER + #ifdef TAOCRYPT_X86ASM_AVAILABLE + #define BigReverse AsmReverse + #else + #define BigReverse ByteReverse + #endif +#else + #define BigReverse +#endif + + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + + // faster than rotate, use bswap + + inline word32 AsmReverse(word32 wd) + { + #ifdef __GNUC__ + __asm__ + ( + "bswap %1" + : "=r"(wd) + : "0"(wd) + ); + #else + __asm + { + mov eax, wd + bswap eax + mov wd, eax + } + #endif + return wd; + } + +#endif + + +template +inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in, + word32 inlen) +{ + const unsigned int U = sizeof(T); + memcpy(out, in, inlen); + memset((byte *)out+inlen, 0, outlen*U-inlen); + ByteReverseIf(out, out, RoundUpToMultipleOf(inlen, U), order); +} + + +#ifdef _MSC_VER + // disable conversion warning + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable:4244 4996) +#endif + + +inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, + byte*) +{ + return block[0]; +} + +inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block, + word16*) +{ + return (order == BigEndianOrder) + ? block[1] | (block[0] << 8) + : block[0] | (block[1] << 8); +} + +inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block, + word32*) +{ + return (order == BigEndianOrder) + ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) + | (word32(block[0]) << 24) + : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) + | (word32(block[3]) << 24); +} + +template +inline T UnalignedGetWord(ByteOrder order, const byte *block, T* dummy = 0) +{ + return UnalignedGetWordNonTemplate(order, block, dummy); +} + +inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, + const byte *xorBlock = 0) +{ + block[0] = xorBlock ? (value ^ xorBlock[0]) : value; +} + +#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y))) + +inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, + const byte *xorBlock = 0) +{ + if (order == BigEndianOrder) + { + block[0] = GETBYTE(value, 1); + block[1] = GETBYTE(value, 0); + } + else + { + block[0] = GETBYTE(value, 0); + block[1] = GETBYTE(value, 1); + } + + if (xorBlock) + { + block[0] ^= xorBlock[0]; + block[1] ^= xorBlock[1]; + } +} + +inline void UnalignedPutWord(ByteOrder order, byte* block, word32 value, + const byte* xorBlock = 0) +{ + if (order == BigEndianOrder) + { + block[0] = GETBYTE(value, 3); + block[1] = GETBYTE(value, 2); + block[2] = GETBYTE(value, 1); + block[3] = GETBYTE(value, 0); + } + else + { + block[0] = GETBYTE(value, 0); + block[1] = GETBYTE(value, 1); + block[2] = GETBYTE(value, 2); + block[3] = GETBYTE(value, 3); + } + + if (xorBlock) + { + block[0] ^= xorBlock[0]; + block[1] ^= xorBlock[1]; + block[2] ^= xorBlock[2]; + block[3] ^= xorBlock[3]; + } +} + + +template +inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) +{ + if (assumeAligned) + return ByteReverseIf(*reinterpret_cast(block), order); + else + return UnalignedGetWord(order, block); +} + +template +inline void GetWord(bool assumeAligned, ByteOrder order, T &result, + const byte *block) +{ + result = GetWord(assumeAligned, order, block); +} + +template +inline void PutWord(bool assumeAligned, ByteOrder order, byte* block, T value, + const byte *xorBlock = 0) +{ + if (assumeAligned) + { + if (xorBlock) + *reinterpret_cast(block) = ByteReverseIf(value, order) + ^ *reinterpret_cast(xorBlock); + else + *reinterpret_cast(block) = ByteReverseIf(value, order); + } + else + UnalignedPutWord(order, block, value, xorBlock); +} + +template +class GetBlock +{ +public: + GetBlock(const void *block) + : m_block((const byte *)block) {} + + template + inline GetBlock & operator()(U &x) + { + TAOCRYPT_COMPILE_ASSERT(sizeof(U) >= sizeof(T)); + x = GetWord(A, B::ToEnum(), m_block); + m_block += sizeof(T); + return *this; + } + +private: + const byte *m_block; +}; + +template +class PutBlock +{ +public: + PutBlock(const void *xorBlock, void *block) + : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {} + + template + inline PutBlock & operator()(U x) + { + PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock); + m_block += sizeof(T); + if (m_xorBlock) + m_xorBlock += sizeof(T); + return *this; + } + +private: + const byte *m_xorBlock; + byte *m_block; +}; + +/* + XXX MYSQL: Setting A (assumeAligned) to false, + keeping it true might trigger segfault on SPARC. +*/ +template +struct BlockGetAndPut +{ + // function needed because of C++ grammatical ambiguity between + // expression-statements and declarations + static inline GetBlock Get(const void *block) + {return GetBlock(block);} + typedef PutBlock Put; +}; + + + +template struct SafeShifter; + +template<> struct SafeShifter +{ + template + static inline T RightShift(T value, unsigned int bits) + { + return 0; + } + + template + static inline T LeftShift(T value, unsigned int bits) + { + return 0; + } +}; + +template<> struct SafeShifter +{ + template + static inline T RightShift(T value, unsigned int bits) + { + return value >> bits; + } + + template + static inline T LeftShift(T value, unsigned int bits) + { + return value << bits; + } +}; + +template +inline T SafeRightShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); +} + +template +inline T SafeLeftShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits); +} + + +inline +word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits) +{ + word u, carry=0; + if (shiftBits) + for (unsigned int i=0; i> (WORD_BITS-shiftBits); + } + return carry; +} + + +inline +word ShiftWordsRightByBits(word* r, unsigned int n, unsigned int shiftBits) +{ + word u, carry=0; + if (shiftBits) + for (int i=n-1; i>=0; i--) + { + u = r[i]; + r[i] = (u >> shiftBits) | carry; + carry = u << (WORD_BITS-shiftBits); + } + return carry; +} + + +inline +void ShiftWordsLeftByWords(word* r, unsigned int n, unsigned int shiftWords) +{ + shiftWords = min(shiftWords, n); + if (shiftWords) + { + for (unsigned int i=n-1; i>=shiftWords; i--) + r[i] = r[i-shiftWords]; + SetWords(r, 0, shiftWords); + } +} + + +inline +void ShiftWordsRightByWords(word* r, unsigned int n, unsigned int shiftWords) +{ + shiftWords = min(shiftWords, n); + if (shiftWords) + { + for (unsigned int i=0; i+shiftWords +inline T1 SaturatingSubtract(T1 a, T2 b) +{ + TAOCRYPT_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0); // T1 is unsigned type + TAOCRYPT_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1); // T2 is unsigned type + return T1((a > b) ? (a - b) : 0); +} + + +// declares +unsigned int BytePrecision(word value); +unsigned int BitPrecision(word); +word Crop(word value, unsigned int size); + + + +} // namespace + +#endif // TAO_CRYPT_MISC_HPP diff --git a/mysql/extra/yassl/taocrypt/include/modarith.hpp b/mysql/extra/yassl/taocrypt/include/modarith.hpp new file mode 100644 index 0000000..5ac3f67 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/modarith.hpp @@ -0,0 +1,165 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* based on Wei Dai's modarith.h from CryptoPP */ + + +#ifndef TAO_CRYPT_MODARITH_HPP +#define TAO_CRYPT_MODARITH_HPP + +#include "misc.hpp" +#include "algebra.hpp" + +namespace TaoCrypt { + + +// ModularArithmetic +class ModularArithmetic : public AbstractRing +{ +public: + + typedef int RandomizationParameter; + typedef Integer Element; + + ModularArithmetic(const Integer &modulus = Integer::One()) + : modulus(modulus), result((word)0, modulus.reg_.size()) {} + + ModularArithmetic(const ModularArithmetic &ma) + : AbstractRing(), + modulus(ma.modulus), result((word)0, modulus.reg_.size()) {} + + const Integer& GetModulus() const {return modulus;} + void SetModulus(const Integer &newModulus) + { + modulus = newModulus; + result.reg_.resize(modulus.reg_.size()); + } + + virtual bool IsMontgomeryRepresentation() const {return false;} + + virtual Integer ConvertIn(const Integer &a) const + {return a%modulus;} + + virtual Integer ConvertOut(const Integer &a) const + {return a;} + + const Integer& Half(const Integer &a) const; + + bool Equal(const Integer &a, const Integer &b) const + {return a==b;} + + const Integer& Identity() const + {return Integer::Zero();} + + const Integer& Add(const Integer &a, const Integer &b) const; + + Integer& Accumulate(Integer &a, const Integer &b) const; + + const Integer& Inverse(const Integer &a) const; + + const Integer& Subtract(const Integer &a, const Integer &b) const; + + Integer& Reduce(Integer &a, const Integer &b) const; + + const Integer& Double(const Integer &a) const + {return Add(a, a);} + + const Integer& MultiplicativeIdentity() const + {return Integer::One();} + + const Integer& Multiply(const Integer &a, const Integer &b) const + {return result1 = a*b%modulus;} + + const Integer& Square(const Integer &a) const + {return result1 = a.Squared()%modulus;} + + bool IsUnit(const Integer &a) const + {return Integer::Gcd(a, modulus).IsUnit();} + + const Integer& MultiplicativeInverse(const Integer &a) const + {return result1 = a.InverseMod(modulus);} + + const Integer& Divide(const Integer &a, const Integer &b) const + {return Multiply(a, MultiplicativeInverse(b));} + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, + const Integer &y, const Integer &e2) const; + + void SimultaneousExponentiate(Element *results, const Element &base, + const Integer *exponents, unsigned int exponentsCount) const; + + unsigned int MaxElementBitLength() const + {return (modulus-1).BitCount();} + + unsigned int MaxElementByteLength() const + {return (modulus-1).ByteCount();} + + + static const RandomizationParameter DefaultRandomizationParameter; + +protected: + Integer modulus; + mutable Integer result, result1; + +}; + + + +//! do modular arithmetics in Montgomery representation for increased speed +class MontgomeryRepresentation : public ModularArithmetic +{ +public: + MontgomeryRepresentation(const Integer &modulus); // modulus must be odd + + bool IsMontgomeryRepresentation() const {return true;} + + Integer ConvertIn(const Integer &a) const + {return (a<<(WORD_BITS*modulus.reg_.size()))%modulus;} + + Integer ConvertOut(const Integer &a) const; + + const Integer& MultiplicativeIdentity() const + {return result1 = Integer::Power2(WORD_BITS*modulus.reg_.size())%modulus;} + + const Integer& Multiply(const Integer &a, const Integer &b) const; + + const Integer& Square(const Integer &a) const; + + const Integer& MultiplicativeInverse(const Integer &a) const; + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, + const Integer &y, const Integer &e2) const + {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousExponentiate(Element *results, const Element &base, + const Integer *exponents, unsigned int exponentsCount) const + {AbstractRing::SimultaneousExponentiate(results, base, + exponents, exponentsCount);} + +private: + Integer u; + mutable AlignedWordBlock workspace; +}; + + + + +} // namespace + +#endif // TAO_CRYPT_MODARITH_HPP diff --git a/mysql/extra/yassl/taocrypt/include/modes.hpp b/mysql/extra/yassl/taocrypt/include/modes.hpp new file mode 100644 index 0000000..bfe8c6e --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/modes.hpp @@ -0,0 +1,154 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* modes.hpp provides ECB and CBC modes for block cipher encryption/decryption +*/ + + +#ifndef TAO_CRYPT_MODES_HPP +#define TAO_CRYPT_MODES_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +enum Mode { ECB, CBC }; + + + +// BlockCipher abstraction +template +class BlockCipher { +public: + BlockCipher() : cipher_(DIR, MODE) {} + + void Process(byte* c, const byte* p, word32 sz) + { cipher_.Process(c, p, sz); } + void SetKey(const byte* k, word32 sz) + { cipher_.SetKey(k, sz, DIR); } + void SetKey(const byte* k, word32 sz, const byte* iv) + { cipher_.SetKey(k, sz, DIR); cipher_.SetIV(iv); } +private: + T cipher_; + + BlockCipher(const BlockCipher&); // hide copy + BlockCipher& operator=(const BlockCipher&); // and assign +}; + + +// Mode Base for block ciphers, static size +class Mode_BASE : public virtual_base { +public: + enum { MaxBlockSz = 16 }; + + explicit Mode_BASE(int sz, CipherDir dir, Mode mode) + : blockSz_(sz), reg_(reinterpret_cast(r_)), + tmp_(reinterpret_cast(t_)), dir_(dir), mode_(mode) + {} + virtual ~Mode_BASE() {} + + virtual void Process(byte*, const byte*, word32); + + void SetIV(const byte* iv) { memcpy(reg_, iv, blockSz_); } +protected: + int blockSz_; + byte* reg_; + byte* tmp_; + + word32 r_[MaxBlockSz / sizeof(word32)]; // align reg_ on word32 + word32 t_[MaxBlockSz / sizeof(word32)]; // align tmp_ on word32 + + CipherDir dir_; + Mode mode_; + + void ECB_Process(byte*, const byte*, word32); + void CBC_Encrypt(byte*, const byte*, word32); + void CBC_Decrypt(byte*, const byte*, word32); + + Mode_BASE(const Mode_BASE&); // hide copy + Mode_BASE& operator=(const Mode_BASE&); // and assign + +private: + virtual void ProcessAndXorBlock(const byte*, const byte*, byte*) const = 0; +}; + + +inline void Mode_BASE::Process(byte* out, const byte* in, word32 sz) +{ + if (mode_ == ECB) + ECB_Process(out, in, sz); + else if (mode_ == CBC) { + if (dir_ == ENCRYPTION) + CBC_Encrypt(out, in, sz); + else + CBC_Decrypt(out, in, sz); + } +} + + +// ECB Process blocks +inline void Mode_BASE::ECB_Process(byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / blockSz_; + + while (blocks--) { + ProcessAndXorBlock(in, 0, out); + out += blockSz_; + in += blockSz_; + } +} + + +// CBC Encrypt +inline void Mode_BASE::CBC_Encrypt(byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / blockSz_; + + while (blocks--) { + xorbuf(reg_, in, blockSz_); + ProcessAndXorBlock(reg_, 0, reg_); + memcpy(out, reg_, blockSz_); + out += blockSz_; + in += blockSz_; + } +} + + +// CBC Decrypt +inline void Mode_BASE::CBC_Decrypt(byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / blockSz_; + byte hold[MaxBlockSz]; + + while (blocks--) { + memcpy(tmp_, in, blockSz_); + ProcessAndXorBlock(tmp_, 0, out); + xorbuf(out, reg_, blockSz_); + memcpy(hold, reg_, blockSz_); // swap reg_ and tmp_ + memcpy(reg_, tmp_, blockSz_); + memcpy(tmp_, hold, blockSz_); + out += blockSz_; + in += blockSz_; + } +} + + +} // namespace + +#endif // TAO_CRYPT_MODES_HPP diff --git a/mysql/extra/yassl/taocrypt/include/pwdbased.hpp b/mysql/extra/yassl/taocrypt/include/pwdbased.hpp new file mode 100644 index 0000000..cf4dff5 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/pwdbased.hpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* pwdbased.hpp defines PBKDF2 from PKCS #5 +*/ + + +#ifndef TAO_CRYPT_PWDBASED_HPP +#define TAO_CRYPT_PWDBASED_HPP + +#include +#include "misc.hpp" +#include "block.hpp" +#include "hmac.hpp" + +namespace TaoCrypt { + + +// From PKCS #5, T must be type suitable for HMAC +template +class PBKDF2_HMAC { +public: + word32 MaxDerivedKeyLength() const { return 0xFFFFFFFFU;} // avoid overflow + + word32 DeriveKey(byte* derived, word32 dLen, const byte* pwd, word32 pLen, + const byte* salt, word32 sLen, word32 iterations) const; +}; + + + +template +word32 PBKDF2_HMAC::DeriveKey(byte* derived, word32 dLen, const byte* pwd, + word32 pLen, const byte* salt, word32 sLen, + word32 iterations) const +{ + if (dLen > MaxDerivedKeyLength()) + return 0; + + ByteBlock buffer(T::DIGEST_SIZE); + HMAC hmac; + + hmac.SetKey(pwd, pLen); + + word32 i = 1; + + while (dLen > 0) { + hmac.Update(salt, sLen); + word32 j; + for (j = 0; j < 4; j++) { + byte b = i >> ((3-j)*8); + hmac.Update(&b, 1); + } + hmac.Final(buffer.get_buffer()); + + word32 segmentLen = min(dLen, buffer.size()); + memcpy(derived, buffer.get_buffer(), segmentLen); + + for (j = 1; j < iterations; j++) { + hmac.Update(buffer.get_buffer(), buffer.size()); + hmac.Final(buffer.get_buffer()); + xorbuf(derived, buffer.get_buffer(), segmentLen); + } + derived += segmentLen; + dLen -= segmentLen; + i++; + } + return iterations; +} + + + + +} // naemspace + +#endif // TAO_CRYPT_PWDBASED_HPP diff --git a/mysql/extra/yassl/taocrypt/include/rabbit.hpp b/mysql/extra/yassl/taocrypt/include/rabbit.hpp new file mode 100644 index 0000000..d3ec947 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/rabbit.hpp @@ -0,0 +1,65 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* rabbit.hpp defines Rabbit +*/ + + +#ifndef TAO_CRYPT_RABBIT_HPP +#define TAO_CRYPT_RABBIT_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +// Rabbit encryption and decryption +class Rabbit { +public: + + typedef Rabbit Encryption; + typedef Rabbit Decryption; + + enum RabbitCtx { Master = 0, Work = 1 }; + + Rabbit() {} + + void Process(byte*, const byte*, word32); + void SetKey(const byte*, const byte*); +private: + struct Ctx { + word32 x[8]; + word32 c[8]; + word32 carry; + }; + + Ctx masterCtx_; + Ctx workCtx_; + + void NextState(RabbitCtx); + void SetIV(const byte*); + + Rabbit(const Rabbit&); // hide copy + const Rabbit operator=(const Rabbit&); // and assign +}; + +} // namespace + + +#endif // TAO_CRYPT_RABBIT_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/random.hpp b/mysql/extra/yassl/taocrypt/include/random.hpp new file mode 100644 index 0000000..70c4c0e --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/random.hpp @@ -0,0 +1,84 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* random.hpp provides a crypto secure Random Number Generator using an OS + specific seed +*/ + + +#ifndef TAO_CRYPT_RANDOM_HPP +#define TAO_CRYPT_RANDOM_HPP + +#include "arc4.hpp" +#include "error.hpp" + +namespace TaoCrypt { + + +// OS specific seeder +class OS_Seed { +public: + OS_Seed(); + ~OS_Seed(); + + void GenerateSeed(byte*, word32 sz); + Error GetError() const { return error_; } +private: +#if defined(_WIN32) + #if defined(_WIN64) + typedef unsigned __int64 ProviderHandle; + // type HCRYPTPROV, avoid #include + #else + typedef unsigned long ProviderHandle; + #endif + ProviderHandle handle_; +#else + int fd_; +#endif + Error error_; + + OS_Seed(const OS_Seed&); // hide copy + OS_Seed& operator=(const OS_Seed&); // hide assign +}; + + +// secure Random Nnumber Generator +class RandomNumberGenerator { +public: + RandomNumberGenerator(); + ~RandomNumberGenerator() {} + + void GenerateBlock(byte*, word32 sz); + byte GenerateByte(); + + ErrorNumber GetError() const { return seed_.GetError().What(); } +private: + OS_Seed seed_; + ARC4 cipher_; + + RandomNumberGenerator(const RandomNumberGenerator&); // hide copy + RandomNumberGenerator operator=(const RandomNumberGenerator&); // && assign +}; + + + + +} // namespace + +#endif // TAO_CRYPT_RANDOM_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/ripemd.hpp b/mysql/extra/yassl/taocrypt/include/ripemd.hpp new file mode 100644 index 0000000..5fb8aa8 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/ripemd.hpp @@ -0,0 +1,69 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* ripemd.hpp provides RIPEMD digest support +*/ + +#ifndef TAO_CRYPT_RIPEMD_HPP +#define TAO_CRYPT_RIPEMD_HPP + +#include "hash.hpp" + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_RIPEMD_ASM +#endif + +namespace TaoCrypt { + + +// RIPEMD160 digest +class RIPEMD160 : public HASHwithTransform { +public: + enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56, + TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes + RIPEMD160() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + RIPEMD160(const RIPEMD160&); + RIPEMD160& operator= (const RIPEMD160&); + +#ifdef DO_RIPEMD_ASM + void Update(const byte*, word32); +#endif + void Init(); + void Swap(RIPEMD160&); +private: + void Transform(); + void AsmTransform(const byte* data, word32 times); +}; + +inline void swap(RIPEMD160& a, RIPEMD160& b) +{ + a.Swap(b); +} + + +} // namespace + +#endif // TAO_CRYPT_RIPEMD_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/rsa.hpp b/mysql/extra/yassl/taocrypt/include/rsa.hpp new file mode 100644 index 0000000..ee3e378 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/rsa.hpp @@ -0,0 +1,250 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* rsa.hpp provides RSA ES encrypt/decrypt, SSL (block type 1) sign and verify +*/ + +#ifndef TAO_CRYPT_RSA_HPP +#define TAO_CRYPT_RSA_HPP + +#include "integer.hpp" +#include "random.hpp" + + +namespace TaoCrypt { + +class Source; + + +// Public Key Length helper +class PK_Lengths { + const Integer& image_; +public: + explicit PK_Lengths(const Integer& i) : image_(i) {} + + word32 PaddedBlockBitLength() const {return image_.BitCount() - 1;} + word32 PaddedBlockByteLength() const + {return BitsToBytes(PaddedBlockBitLength());} + + word32 FixedCiphertextLength() const {return image_.ByteCount();} + word32 FixedMaxPlaintextLength() const + {return SaturatingSubtract(PaddedBlockBitLength() / 8, 10U); } +}; + + +// RSA Public Key +class RSA_PublicKey { +protected: + Integer n_; + Integer e_; +public: + RSA_PublicKey() {} + explicit RSA_PublicKey(Source&); + + void Initialize(const Integer& n, const Integer& e) {n_ = n; e_ = e;} + void Initialize(Source&); + + Integer ApplyFunction(const Integer& x) const; + + const Integer& GetModulus() const {return n_;} + const Integer& GetPublicExponent() const {return e_;} + + void SetModulus(const Integer& n) {n_ = n;} + void SetPublicExponent(const Integer& e) {e_ = e;} + + word32 FixedCiphertextLength() + { + return PK_Lengths(n_).FixedCiphertextLength(); + } + + RSA_PublicKey(const RSA_PublicKey& other) : n_(other.n_), e_(other.e_) {} + RSA_PublicKey& operator=(const RSA_PublicKey& that) + { + RSA_PublicKey tmp(that); + Swap(tmp); + return *this; + } + + void Swap(RSA_PublicKey& other) + { + n_.Swap(other.n_); + e_.Swap(other.e_); + } +}; + + +// RSA Private Key +class RSA_PrivateKey : public RSA_PublicKey { + Integer d_; + Integer p_; + Integer q_; + Integer dp_; + Integer dq_; + Integer u_; +public: + RSA_PrivateKey() {} + explicit RSA_PrivateKey(Source&); + + void Initialize(const Integer& n, const Integer& e, const Integer& d, + const Integer& p, const Integer& q, const Integer& dp, + const Integer& dq, const Integer& u) + {n_ = n; e_ = e; d_ = d; p_ = p; q_ = q; dp_ = dp; dq_ = dq; u_ = u;} + void Initialize(Source&); + + Integer CalculateInverse(RandomNumberGenerator&, const Integer&) const; + + const Integer& GetPrime1() const {return p_;} + const Integer& GetPrime2() const {return q_;} + const Integer& GetPrivateExponent() const {return d_;} + const Integer& GetModPrime1PrivateExponent() const {return dp_;} + const Integer& GetModPrime2PrivateExponent() const {return dq_;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const + {return u_;} + + void SetPrime1(const Integer& p) {p_ = p;} + void SetPrime2(const Integer& q) {q_ = q;} + void SetPrivateExponent(const Integer& d) {d_ = d;} + void SetModPrime1PrivateExponent(const Integer& dp) {dp_ = dp;} + void SetModPrime2PrivateExponent(const Integer& dq) {dq_ = dq;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer& u) {u_ = u;} +private: + RSA_PrivateKey(const RSA_PrivateKey&); // hide copy + RSA_PrivateKey& operator=(const RSA_PrivateKey&); // and assign +}; + + +// block type 2 padding +class RSA_BlockType2 { +public: + void Pad(const byte*, word32, byte*, word32, + RandomNumberGenerator&) const; + word32 UnPad(const byte*, word32, byte*) const; +}; + + +// block type 1 padding +class RSA_BlockType1 { +public: + void Pad(const byte*, word32, byte*, word32, + RandomNumberGenerator&) const; + word32 UnPad(const byte*, word32, byte*) const; +}; + + +// RSA Encryptor, can use any padding +template +class RSA_Encryptor { + const RSA_PublicKey& key_; + Pad padding_; +public: + explicit RSA_Encryptor(const RSA_PublicKey& k) : key_(k) {} + + void Encrypt(const byte*, word32, byte*, RandomNumberGenerator&); + bool SSL_Verify(const byte* msg, word32 sz, const byte* sig); +}; + + +// RSA Decryptor, can use any padding +template +class RSA_Decryptor { + const RSA_PrivateKey& key_; + Pad padding_; +public: + explicit RSA_Decryptor(const RSA_PrivateKey& k) : key_(k) {} + + word32 Decrypt(const byte*, word32, byte*, RandomNumberGenerator&); + void SSL_Sign(const byte*, word32, byte*, RandomNumberGenerator&); +}; + + +// Public Encrypt +template +void RSA_Encryptor::Encrypt(const byte* plain, word32 sz, byte* cipher, + RandomNumberGenerator& rng) +{ + PK_Lengths lengths(key_.GetModulus()); + if (sz > lengths.FixedMaxPlaintextLength()) + return; + + ByteBlock paddedBlock(lengths.PaddedBlockByteLength()); + padding_.Pad(plain, sz, paddedBlock.get_buffer(), + lengths.PaddedBlockBitLength(), rng); + + key_.ApplyFunction(Integer(paddedBlock.get_buffer(), paddedBlock.size())). + Encode(cipher, lengths.FixedCiphertextLength()); +} + + +// Private Decrypt +template +word32 RSA_Decryptor::Decrypt(const byte* cipher, word32 sz, byte* plain, + RandomNumberGenerator& rng) +{ + PK_Lengths lengths(key_.GetModulus()); + + if (sz != lengths.FixedCiphertextLength()) + return 0; + + ByteBlock paddedBlock(lengths.PaddedBlockByteLength()); + Integer x = key_.CalculateInverse(rng, Integer(cipher, + lengths.FixedCiphertextLength()).Ref()); + if (x.ByteCount() > paddedBlock.size()) + x = Integer::Zero(); // don't return false, prevents timing attack + x.Encode(paddedBlock.get_buffer(), paddedBlock.size()); + return padding_.UnPad(paddedBlock.get_buffer(), + lengths.PaddedBlockBitLength(), plain); +} + + +// Private SSL type (block 1) Encrypt +template +void RSA_Decryptor::SSL_Sign(const byte* message, word32 sz, byte* sig, + RandomNumberGenerator& rng) +{ + RSA_PublicKey inverse; + inverse.Initialize(key_.GetModulus(), key_.GetPrivateExponent()); + RSA_Encryptor enc(inverse); // SSL Type + enc.Encrypt(message, sz, sig, rng); +} + + +word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain); + + +// Public SSL type (block 1) Decrypt +template +bool RSA_Encryptor::SSL_Verify(const byte* message, word32 sz, + const byte* sig) +{ + ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength()); + if (SSL_Decrypt(key_, sig, plain.get_buffer()) != sz) + return false; // not right justified or bad padding + + if ( (memcmp(plain.get_buffer(), message, sz)) == 0) + return true; + return false; +} + + +typedef RSA_Encryptor<> RSAES_Encryptor; +typedef RSA_Decryptor<> RSAES_Decryptor; + + +} // namespace + +#endif // TAO_CRYPT_RSA_HPP diff --git a/mysql/extra/yassl/taocrypt/include/runtime.hpp b/mysql/extra/yassl/taocrypt/include/runtime.hpp new file mode 100644 index 0000000..c984287 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/runtime.hpp @@ -0,0 +1,60 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* runtime.hpp provides C++ runtime support functions when building a pure C + * version of yaSSL, user must define YASSL_PURE_C +*/ + + + +#ifndef yaSSL_NEW_HPP +#define yaSSL_NEW_HPP + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef YASSL_PURE_C + +#ifdef __sun + + +// Handler for pure virtual functions +namespace __Crun { + void pure_error(void); +} // namespace __Crun + +#endif // __sun + + +#if defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + +#if __GNUC__ > 2 + +extern "C" { +#if defined(DO_TAOCRYPT_KERNEL_MODE) + #include "kernelc.hpp" +#endif + int __cxa_pure_virtual () __attribute__ ((weak)); +} // extern "C" + +#endif // __GNUC__ > 2 +#endif // compiler check +#endif // YASSL_PURE_C +#endif // yaSSL_NEW_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/sha.hpp b/mysql/extra/yassl/taocrypt/include/sha.hpp new file mode 100644 index 0000000..cf6d0d0 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/sha.hpp @@ -0,0 +1,174 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* sha.hpp provides SHA-1 digests, see RFC 3174 +*/ + +#ifndef TAO_CRYPT_SHA_HPP +#define TAO_CRYPT_SHA_HPP + +#include "hash.hpp" + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_SHA_ASM +#endif + +namespace TaoCrypt { + + +// SHA-1 digest +class SHA : public HASHwithTransform { +public: + enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56, + TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes + SHA() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + +#ifdef DO_SHA_ASM + void Update(const byte* data, word32 len); +#endif + void Init(); + + SHA(const SHA&); + SHA& operator= (const SHA&); + + void Swap(SHA&); +private: + void Transform(); + void AsmTransform(const byte* data, word32 times); +}; + + +inline void swap(SHA& a, SHA& b) +{ + a.Swap(b); +} + +// SHA-256 digest +class SHA256 : public HASHwithTransform { +public: + enum { BLOCK_SIZE = 64, DIGEST_SIZE = 32, PAD_SIZE = 56, + TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes + SHA256() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + void Init(); + + SHA256(const SHA256&); + SHA256& operator= (const SHA256&); + + void Swap(SHA256&); +private: + void Transform(); +}; + + +// SHA-224 digest +class SHA224 : public HASHwithTransform { +public: + enum { BLOCK_SIZE = 64, DIGEST_SIZE = 28, PAD_SIZE = 56, + TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes + SHA224() : HASHwithTransform(SHA256::DIGEST_SIZE /sizeof(word32),BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + void Init(); + + SHA224(const SHA224&); + SHA224& operator= (const SHA224&); + + void Swap(SHA224&); +private: + void Transform(); +}; + + +#ifdef WORD64_AVAILABLE + +// SHA-512 digest +class SHA512 : public HASH64withTransform { +public: + enum { BLOCK_SIZE = 128, DIGEST_SIZE = 64, PAD_SIZE = 112, + TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes + SHA512() : HASH64withTransform(DIGEST_SIZE / sizeof(word64), BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + void Init(); + + SHA512(const SHA512&); + SHA512& operator= (const SHA512&); + + void Swap(SHA512&); +private: + void Transform(); +}; + + +// SHA-384 digest +class SHA384 : public HASH64withTransform { +public: + enum { BLOCK_SIZE = 128, DIGEST_SIZE = 48, PAD_SIZE = 112, + TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes + SHA384() : HASH64withTransform(SHA512::DIGEST_SIZE/ sizeof(word64), + BLOCK_SIZE) + { Init(); } + ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); } + word32 getBlockSize() const { return BLOCK_SIZE; } + word32 getDigestSize() const { return DIGEST_SIZE; } + word32 getPadSize() const { return PAD_SIZE; } + + void Init(); + + SHA384(const SHA384&); + SHA384& operator= (const SHA384&); + + void Swap(SHA384&); +private: + void Transform(); +}; + +enum { MAX_SHA2_DIGEST_SIZE = 64 }; // SHA512 + +#else + +enum { MAX_SHA2_DIGEST_SIZE = 32 }; // SHA256 + +#endif // WORD64_AVAILABLE + + +} // namespace + + +#endif // TAO_CRYPT_SHA_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/twofish.hpp b/mysql/extra/yassl/taocrypt/include/twofish.hpp new file mode 100644 index 0000000..eeb9b6a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/twofish.hpp @@ -0,0 +1,94 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* twofish.hpp defines Twofish +*/ + + +#ifndef TAO_CRYPT_TWOFISH_HPP +#define TAO_CRYPT_TWOFISH_HPP + +#include "misc.hpp" +#include "modes.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_TWOFISH_ASM +#endif + +namespace TaoCrypt { + +enum { TWOFISH_BLOCK_SIZE = 16 }; + + +// Twofish encryption and decryption, see +class Twofish : public Mode_BASE { +public: + enum { BLOCK_SIZE = TWOFISH_BLOCK_SIZE }; + + Twofish(CipherDir DIR, Mode MODE) + : Mode_BASE(BLOCK_SIZE, DIR, MODE) {} + +#ifdef DO_TWOFISH_ASM + void Process(byte*, const byte*, word32); +#endif + void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); + void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } +private: + static const byte q_[2][256]; + static const word32 mds_[4][256]; + + word32 k_[40]; + word32 s_[4][256]; + + static word32 h0(word32 x, const word32 *key, unsigned int kLen); + static word32 h(word32 x, const word32 *key, unsigned int kLen); + + void ProcessAndXorBlock(const byte*, const byte*, byte*) const; + + void encrypt(const byte*, const byte*, byte*) const; + void decrypt(const byte*, const byte*, byte*) const; + + void AsmEncrypt(const byte* inBlock, byte* outBlock) const; + void AsmDecrypt(const byte* inBlock, byte* outBlock) const; + + Twofish(const Twofish&); // hide copy + Twofish& operator=(const Twofish&); // and assign +}; + + +typedef BlockCipher Twofish_ECB_Encryption; +typedef BlockCipher Twofish_ECB_Decryption; + +typedef BlockCipher Twofish_CBC_Encryption; +typedef BlockCipher Twofish_CBC_Decryption; + + + +} // naemspace + +#endif // TAO_CRYPT_TWOFISH_HPP + diff --git a/mysql/extra/yassl/taocrypt/include/type_traits.hpp b/mysql/extra/yassl/taocrypt/include/type_traits.hpp new file mode 100644 index 0000000..8c6fe53 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/type_traits.hpp @@ -0,0 +1,77 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* type_traits defines fundamental types + * see discussion in C++ Templates, $19.1 +*/ + + +#ifndef TAO_CRYPT_TYPE_TRAITS_HPP +#define TAO_CRYPT_TYPE_TRAITS_HPP + +#include "types.hpp" + +namespace TaoCrypt { + + +// primary template: in general T is not a fundamental type + +template +class IsFundamentalType { + public: + enum { Yes = 0, No = 1 }; +}; + + +// macro to specialize for fundamental types +#define MK_FUNDAMENTAL_TYPE(T) \ + template<> class IsFundamentalType { \ + public: \ + enum { Yes = 1, No = 0 }; \ + }; + + +MK_FUNDAMENTAL_TYPE(void) + +MK_FUNDAMENTAL_TYPE(bool) +MK_FUNDAMENTAL_TYPE( char) +MK_FUNDAMENTAL_TYPE(signed char) +MK_FUNDAMENTAL_TYPE(unsigned char) + +MK_FUNDAMENTAL_TYPE(signed short) +MK_FUNDAMENTAL_TYPE(unsigned short) +MK_FUNDAMENTAL_TYPE(signed int) +MK_FUNDAMENTAL_TYPE(unsigned int) +MK_FUNDAMENTAL_TYPE(signed long) +MK_FUNDAMENTAL_TYPE(unsigned long) + +MK_FUNDAMENTAL_TYPE(float) +MK_FUNDAMENTAL_TYPE( double) +MK_FUNDAMENTAL_TYPE(long double) + +#if defined(WORD64_AVAILABLE) && defined(WORD64_IS_DISTINCT_TYPE) + MK_FUNDAMENTAL_TYPE(word64) +#endif + + +#undef MK_FUNDAMENTAL_TYPE + + +} // namespace + +#endif // TAO_CRYPT_TYPE_TRAITS_HPP diff --git a/mysql/extra/yassl/taocrypt/include/types.hpp b/mysql/extra/yassl/taocrypt/include/types.hpp new file mode 100644 index 0000000..67ea260 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/include/types.hpp @@ -0,0 +1,99 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's misc.h from CryptoPP, basic crypt types */ + + +#ifndef TAO_CRYPT_TYPES_HPP +#define TAO_CRYPT_TYPES_HPP + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +namespace TaoCrypt { + + +#if defined(WORDS_BIGENDIAN) || (defined(__MWERKS__) && !defined(__INTEL__)) + #define BIG_ENDIAN_ORDER +#endif + +#ifndef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER +#endif + + +typedef unsigned char byte; +typedef unsigned short word16; +typedef unsigned int word32; + +#if defined(_MSC_VER) || defined(__BCPLUSPLUS__) + #define WORD64_AVAILABLE + #define WORD64_IS_DISTINCT_TYPE + typedef unsigned __int64 word64; + #define W64LIT(x) x##ui64 +#elif SIZEOF_LONG == 8 + #define WORD64_AVAILABLE + typedef unsigned long word64; + #define W64LIT(x) x##LL +#elif SIZEOF_LONG_LONG == 8 + #define WORD64_AVAILABLE + #define WORD64_IS_DISTINCT_TYPE + typedef unsigned long long word64; + #define W64LIT(x) x##LL +#endif + + +// compilers we've found 64-bit multiply insructions for +#if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX) + #if !(defined(__ICC) || defined(__INTEL_COMPILER)) + #define HAVE_64_MULTIPLY + #endif +#endif + + +#if defined(HAVE_64_MULTIPLY) && (defined(__ia64__) \ + || defined(_ARCH_PPC64) || defined(__mips64) || defined(__x86_64__) \ + || defined(_M_X64) || defined(_M_IA64)) +// These platforms have 64-bit CPU registers. Unfortunately most C++ compilers +// don't allow any way to access the 64-bit by 64-bit multiply instruction +// without using assembly, so in order to use word64 as word, the assembly +// instruction must be defined in Dword::Multiply(). + typedef word32 hword; + typedef word64 word; +#else + #define TAOCRYPT_NATIVE_DWORD_AVAILABLE + #ifdef WORD64_AVAILABLE + #define TAOCRYPT_SLOW_WORD64 + typedef word16 hword; + typedef word32 word; + typedef word64 dword; + #else + typedef byte hword; + typedef word16 word; + typedef word32 dword; + #endif +#endif + +const word32 WORD_SIZE = sizeof(word); +const word32 WORD_BITS = WORD_SIZE * 8; + + +} // namespace + +#endif // TAO_CRYPT_TYPES_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/algorithm.hpp b/mysql/extra/yassl/taocrypt/mySTL/algorithm.hpp new file mode 100644 index 0000000..83be964 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/algorithm.hpp @@ -0,0 +1,108 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL algorithm implements max, min, for_each, swap, find_if, copy, + * copy_backward, fill + */ + +#ifndef mySTL_ALGORITHM_HPP +#define mySTL_ALGORITHM_HPP + + +namespace mySTL { + + +template +inline const T& max(const T& a, const T&b) +{ + return a < b ? b : a; +} + + +template +inline const T& min(const T& a, const T&b) +{ + return b < a ? b : a; +} + + +template +Func for_each(InIter first, InIter last, Func op) +{ + while (first != last) { + op(*first); + ++first; + } + return op; +} + + +template +inline void swap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +template +InIter find_if(InIter first, InIter last, Pred pred) +{ + while (first != last && !pred(*first)) + ++first; + return first; +} + + +template +inline OutputIter copy(InputIter first, InputIter last, OutputIter place) +{ + while (first != last) { + *place = *first; + ++first; + ++place; + } + return place; +} + + +template +inline OutputIter +copy_backward(InputIter first, InputIter last, OutputIter place) +{ + while (first != last) + *--place = *--last; + return place; +} + + +template +void fill(InputIter first, InputIter last, const T& v) +{ + while (first != last) { + *first = v; + ++first; + } +} + + +} // namespace mySTL + +#endif // mySTL_ALGORITHM_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/helpers.hpp b/mysql/extra/yassl/taocrypt/mySTL/helpers.hpp new file mode 100644 index 0000000..fc6e89d --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/helpers.hpp @@ -0,0 +1,153 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL helpers implements misc constructs for vector and list + * + */ + +#ifndef mySTL_HELPERS_HPP +#define mySTL_HELPERS_HPP + +#include +#ifdef _MSC_VER + #include +#endif + +/* + Workaround for the lack of operator new(size_t, void*) + in IBM VA C++ 6.0 + Also used as a workaround to avoid including +*/ + struct Dummy {}; + + inline void* operator new(size_t size, Dummy* d) + { + return static_cast(d); + } + + // for compilers that want matching delete + inline void operator delete(void* ptr, Dummy* d) + { + } + + typedef Dummy* yassl_pointer; + +namespace mySTL { + + +template +inline void construct(T* p, const T2& value) +{ + new (reinterpret_cast(p)) T(value); +} + + +template +inline void construct(T* p) +{ + new (reinterpret_cast(p)) T(); +} + + +template +inline void destroy(T* p) +{ + p->~T(); +} + + +template +void destroy(Iter first, Iter last) +{ + while (first != last) { + destroy(&*first); + ++first; + } +} + + +template +PlaceIter uninit_copy(Iter first, Iter last, PlaceIter place) +{ + while (first != last) { + construct(&*place, *first); + ++first; + ++place; + } + return place; +} + + +template +PlaceIter uninit_fill_n(PlaceIter place, Size n, const T& value) +{ + while (n) { + construct(&*place, value); + --n; + ++place; + } + return place; +} + + +template +T* GetArrayMemory(size_t items) +{ + unsigned char* ret; + + #ifdef YASSL_LIB + ret = NEW_YS unsigned char[sizeof(T) * items]; + #else + ret = NEW_TC unsigned char[sizeof(T) * items]; + #endif + + return reinterpret_cast(ret); +} + + +template +void FreeArrayMemory(T* ptr) +{ + unsigned char* p = reinterpret_cast(ptr); + + #ifdef YASSL_LIB + yaSSL::ysArrayDelete(p); + #else + TaoCrypt::tcArrayDelete(p); + #endif +} + + + +inline void* GetMemory(size_t bytes) +{ + return GetArrayMemory(bytes); +} + + +inline void FreeMemory(void* ptr) +{ + FreeArrayMemory(ptr); +} + + + +} // namespace mySTL + +#endif // mySTL_HELPERS_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/list.hpp b/mysql/extra/yassl/taocrypt/mySTL/list.hpp new file mode 100644 index 0000000..df03e0a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/list.hpp @@ -0,0 +1,367 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL list implements a simple list + * + */ + +#ifndef mySTL_LIST_HPP +#define mySTL_LIST_HPP + + +#include "helpers.hpp" + + +namespace mySTL { + + + +template +class list { + +#ifdef __SUNPRO_CC +/* + Sun Forte 7 C++ v. 5.4 needs class 'node' public to be visible to + the nested class 'iterator' (a non-standard behaviour). +*/ +public: +#endif + + struct node { + node(T t) : prev_(0), next_(0), value_(t) {} + + node* prev_; + node* next_; + T value_; + }; +public: + list() : head_(0), tail_(0), sz_(0) {} + ~list(); + + void push_front(T); + void pop_front(); + T front() const; + void push_back(T); + void pop_back(); + T back() const; + bool remove(T); + size_t size() const { return sz_; } + bool empty() const { return sz_ == 0; } + + class iterator { + node* current_; + public: + explicit iterator(node* p = 0) : current_(p) {} + + T& operator*() const + { + return current_->value_; + } + + T* operator->() const + { + return &(operator*()); + } + + iterator& operator++() + { + current_ = current_->next_; + return *this; + } + + iterator& operator--() + { + current_ = current_->prev_; + return *this; + } + + iterator operator++(int) + { + iterator tmp = *this; + current_ = current_->next_; + return tmp; + } + + iterator operator--(int) + { + iterator tmp = *this; + current_ = current_->prev_; + return tmp; + } + + bool operator==(const iterator& other) const + { + return current_ == other.current_; + } + + bool operator!=(const iterator& other) const + { + return current_ != other.current_; + } + + friend class list; + }; + + + class reverse_iterator { + node* current_; + public: + explicit reverse_iterator(node* p = 0) : current_(p) {} + + T& operator*() const + { + return current_->value_; + } + + T* operator->() const + { + return &(operator*()); + } + + reverse_iterator& operator++() + { + current_ = current_->prev_; + return *this; + } + + reverse_iterator& operator--() + { + current_ = current_->next_; + return *this; + } + + reverse_iterator operator++(int) + { + reverse_iterator tmp = *this; + current_ = current_->prev_; + return tmp; + } + + reverse_iterator operator--(int) + { + reverse_iterator tmp = *this; + current_ = current_->next_; + return tmp; + } + + bool operator==(const reverse_iterator& other) const + { + return current_ == other.current_; + } + + bool operator!=(const reverse_iterator& other) const + { + return current_ != other.current_; + } + + friend class list; + }; + + bool erase(iterator); + + iterator begin() const { return iterator(head_); } + reverse_iterator rbegin() const { return reverse_iterator(tail_); } + iterator end() const { return iterator(); } + reverse_iterator rend() const { return reverse_iterator(); } + + typedef iterator const_iterator; // for now + + class underflow {}; + class overflow {}; +private: + node* head_; + node* tail_; + size_t sz_; + + node* look_up(T); + + list(const list&); // hide copy + list& operator=(const list&); // and assign +}; + + +template +list::~list() +{ + node* start = head_; + node* next_; + + for (; start; start = next_) { + next_ = start->next_; + destroy(start); + FreeMemory(start); + } +} + + +template +void list::push_front(T t) +{ + void* mem = GetMemory(sizeof(node)); + node* add = new (reinterpret_cast(mem)) node(t); + + if (head_) { + add->next_ = head_; + head_->prev_ = add; + } + else + tail_ = add; + + head_ = add; + ++sz_; +} + + +template +void list::pop_front() +{ + node* front = head_; + + if (head_ == 0) + return; + else if (head_ == tail_) + head_ = tail_ = 0; + else { + head_ = head_->next_; + head_->prev_ = 0; + } + destroy(front); + FreeMemory(front); + --sz_; +} + + +template +T list::front() const +{ + if (head_ == 0) return T(); + return head_->value_; +} + + +template +void list::push_back(T t) +{ + void* mem = GetMemory(sizeof(node)); + node* add = new (reinterpret_cast(mem)) node(t); + + if (tail_) { + tail_->next_ = add; + add->prev_ = tail_; + } + else + head_ = add; + + tail_ = add; + ++sz_; +} + + +template +void list::pop_back() +{ + node* rear = tail_; + + if (tail_ == 0) + return; + else if (tail_ == head_) + tail_ = head_ = 0; + else { + tail_ = tail_->prev_; + tail_->next_ = 0; + } + destroy(rear); + FreeMemory(rear); + --sz_; +} + + +template +T list::back() const +{ + if (tail_ == 0) return T(); + return tail_->value_; +} + + +template +typename list::node* list::look_up(T t) +{ + node* list = head_; + + if (list == 0) return 0; + + for (; list; list = list->next_) + if (list->value_ == t) + return list; + + return 0; +} + + +template +bool list::remove(T t) +{ + node* del = look_up(t); + + if (del == 0) + return false; + else if (del == head_) + pop_front(); + else if (del == tail_) + pop_back(); + else { + del->prev_->next_ = del->next_; + del->next_->prev_ = del->prev_; + + destroy(del); + FreeMemory(del); + --sz_; + } + return true; +} + + +template +bool list::erase(iterator iter) +{ + node* del = iter.current_; + + if (del == 0) + return false; + else if (del == head_) + pop_front(); + else if (del == tail_) + pop_back(); + else { + del->prev_->next_ = del->next_; + del->next_->prev_ = del->prev_; + + destroy(del); + FreeMemory(del); + --sz_; + } + return true; +} + + + +} // namespace mySTL + +#endif // mySTL_LIST_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/memory.hpp b/mysql/extra/yassl/taocrypt/mySTL/memory.hpp new file mode 100644 index 0000000..7e709be --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/memory.hpp @@ -0,0 +1,136 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL memory implements auto_ptr + * + */ + +#ifndef mySTL_MEMORY_HPP +#define mySTL_MEMORY_HPP + +#include "memory_array.hpp" // for auto_array + +#ifdef _MSC_VER + // disable operator-> warning for builtins + #pragma warning(disable:4284) +#endif + + +namespace mySTL { + + +template +struct auto_ptr_ref { + T* ptr_; + explicit auto_ptr_ref(T* p) : ptr_(p) {} +}; + + +template +class auto_ptr { + T* ptr_; + + void Destroy() + { + #ifdef YASSL_LIB + yaSSL::ysDelete(ptr_); + #else + TaoCrypt::tcDelete(ptr_); + #endif + } +public: + explicit auto_ptr(T* p = 0) : ptr_(p) {} + + ~auto_ptr() + { + Destroy(); + } + + + auto_ptr(auto_ptr& other) : ptr_(other.release()) {} + + auto_ptr& operator=(auto_ptr& that) + { + if (this != &that) { + Destroy(); + ptr_ = that.release(); + } + return *this; + } + + + T* operator->() const + { + return ptr_; + } + + T& operator*() const + { + return *ptr_; + } + + T* get() const + { + return ptr_; + } + + T* release() + { + T* tmp = ptr_; + ptr_ = 0; + return tmp; + } + + void reset(T* p = 0) + { + if (ptr_ != p) { + Destroy(); + ptr_ = p; + } + } + + // auto_ptr_ref conversions + auto_ptr(auto_ptr_ref ref) : ptr_(ref.ptr_) {} + + auto_ptr& operator=(auto_ptr_ref ref) + { + if (this->ptr_ != ref.ptr_) { + Destroy(); + ptr_ = ref.ptr_; + } + return *this; + } + + template + operator auto_ptr() + { + return auto_ptr(this->release()); + } + + template + operator auto_ptr_ref() + { + return auto_ptr_ref(this->release()); + } +}; + + +} // namespace mySTL + +#endif // mySTL_MEMORY_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/memory_array.hpp b/mysql/extra/yassl/taocrypt/mySTL/memory_array.hpp new file mode 100644 index 0000000..1c238d9 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/memory_array.hpp @@ -0,0 +1,135 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL memory_arry implements auto_array + * + */ + +#ifndef mySTL_MEMORY_ARRAY_HPP +#define mySTL_MEMORY_ARRAY_HPP + + +#ifdef _MSC_VER + // disable operator-> warning for builtins + #pragma warning(disable:4284) +#endif + + +namespace mySTL { + + +template +struct auto_array_ref { + T* ptr_; + explicit auto_array_ref(T* p) : ptr_(p) {} +}; + + +template +class auto_array { + T* ptr_; + + void Destroy() + { + #ifdef YASSL_LIB + yaSSL::ysArrayDelete(ptr_); + #else + TaoCrypt::tcArrayDelete(ptr_); + #endif + } +public: + explicit auto_array(T* p = 0) : ptr_(p) {} + + ~auto_array() + { + Destroy(); + } + + + auto_array(auto_array& other) : ptr_(other.release()) {} + + auto_array& operator=(auto_array& that) + { + if (this != &that) { + Destroy(); + ptr_ = that.release(); + } + return *this; + } + + + T* operator->() const + { + return ptr_; + } + + T& operator*() const + { + return *ptr_; + } + + T* get() const + { + return ptr_; + } + + T* release() + { + T* tmp = ptr_; + ptr_ = 0; + return tmp; + } + + void reset(T* p = 0) + { + if (ptr_ != p) { + Destroy(); + ptr_ = p; + } + } + + // auto_array_ref conversions + auto_array(auto_array_ref ref) : ptr_(ref.ptr_) {} + + auto_array& operator=(auto_array_ref ref) + { + if (this->ptr_ != ref.ptr_) { + Destroy(); + ptr_ = ref.ptr_; + } + return *this; + } + + template + operator auto_array() + { + return auto_array(this->release()); + } + + template + operator auto_array_ref() + { + return auto_array_ref(this->release()); + } +}; + + +} // namespace mySTL + +#endif // mySTL_MEMORY_ARRAY_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/pair.hpp b/mysql/extra/yassl/taocrypt/mySTL/pair.hpp new file mode 100644 index 0000000..545827a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/pair.hpp @@ -0,0 +1,58 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL pair implements pair + * + */ + +#ifndef mySTL_PAIR_HPP +#define mySTL_PAIR_HPP + + + +namespace mySTL { + + +template +struct pair { + typedef T1 first_type; + typedef T2 second_type; + + first_type first; + second_type second; + + pair() {} + pair(const T1& t1, const T2& t2) : first(t1), second(t2) {} + + template + pair(const pair& p) : first(p.first), second(p.second) {} +}; + + +template +inline pair make_pair(const T1& a, const T2& b) +{ + return pair(a, b); +} + + + +} // namespace mySTL + +#endif // mySTL_PAIR_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/stdexcept.hpp b/mysql/extra/yassl/taocrypt/mySTL/stdexcept.hpp new file mode 100644 index 0000000..79ae6de --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/stdexcept.hpp @@ -0,0 +1,76 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL memory implements exception, runtime_error + * + */ + +#ifndef mySTL_STDEXCEPT_HPP +#define mySTL_STDEXCEPT_HPP + + +#include // strncpy +#include // size_t + + +namespace mySTL { + + +class exception { +public: + exception() {} + virtual ~exception() {} // to shut up compiler warnings + + virtual const char* what() const { return ""; } + + // for compiler generated call, never used + static void operator delete(void*) { } +private: + // don't allow dynamic creation of exceptions + static void* operator new(size_t); +}; + + +class named_exception : public exception { +public: + enum { NAME_SIZE = 80 }; + + explicit named_exception(const char* str) + { + strncpy(name_, str, NAME_SIZE); + name_[NAME_SIZE - 1] = 0; + } + + virtual const char* what() const { return name_; } +private: + char name_[NAME_SIZE]; +}; + + +class runtime_error : public named_exception { +public: + explicit runtime_error(const char* str) : named_exception(str) {} +}; + + + + +} // namespace mySTL + +#endif // mySTL_STDEXCEPT_HPP diff --git a/mysql/extra/yassl/taocrypt/mySTL/vector.hpp b/mysql/extra/yassl/taocrypt/mySTL/vector.hpp new file mode 100644 index 0000000..f3702b7 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/mySTL/vector.hpp @@ -0,0 +1,153 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* mySTL vector implements simple vector, w/ swap + * + */ + +#ifndef mySTL_VECTOR_HPP +#define mySTL_VECTOR_HPP + +#include "helpers.hpp" // construct, destory, fill, etc. +#include "algorithm.hpp" // swap + + +namespace mySTL { + + +template +struct vector_base { + T* start_; + T* finish_; + T* end_of_storage_; + + vector_base() : start_(0), finish_(0), end_of_storage_(0) {} + vector_base(size_t n) + { + start_ = GetArrayMemory(n); + finish_ = start_; + end_of_storage_ = start_ + n; + } + + ~vector_base() + { + FreeArrayMemory(start_); + } + + void Swap(vector_base& that) + { + swap(start_, that.start_); + swap(finish_, that.finish_); + swap(end_of_storage_, that.end_of_storage_); + } +}; + + + +template +class vector { +public: + typedef T* iterator; + typedef const T* const_iterator; + + vector() {} + explicit vector(size_t n) : vec_(n) + { + vec_.finish_ = uninit_fill_n(vec_.start_, n, T()); + } + + ~vector() { destroy(vec_.start_, vec_.finish_); } + + vector(const vector& other) : vec_(other.size()) + { + vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_, + vec_.start_); + } + + size_t capacity() const { return vec_.end_of_storage_ - vec_.start_; } + + size_t size() const { return vec_.finish_ - vec_.start_; } + + T& operator[](size_t idx) { return *(vec_.start_ + idx); } + const T& operator[](size_t idx) const { return *(vec_.start_ + idx); } + + const T* begin() const { return vec_.start_; } + const T* end() const { return vec_.finish_; } + + void push_back(const T& v) + { + if (vec_.finish_ != vec_.end_of_storage_) { + construct(vec_.finish_, v); + ++vec_.finish_; + } + else { + vector tmp(size() * 2 + 1, *this); + construct(tmp.vec_.finish_, v); + ++tmp.vec_.finish_; + Swap(tmp); + } + } + + void resize(size_t n, const T& v) + { + if (n == size()) return; + + if (n < size()) { + T* first = vec_.start_ + n; + destroy(first, vec_.finish_); + vec_.finish_ -= vec_.finish_ - first; + } + else { + vector tmp(n, *this); + tmp.vec_.finish_ = uninit_fill_n(tmp.vec_.finish_, n - size(), v); + Swap(tmp); + } + } + + void reserve(size_t n) + { + if (capacity() < n) { + vector tmp(n, *this); + Swap(tmp); + } + } + + void Swap(vector& that) + { + vec_.Swap(that.vec_); + } +private: + vector_base vec_; + + vector& operator=(const vector&); // hide assign + + // for growing, n must be bigger than other size + vector(size_t n, const vector& other) : vec_(n) + { + if (n > other.size()) + vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_, + vec_.start_); + } +}; + + + +} // namespace mySTL + +#endif // mySTL_VECTOR_HPP diff --git a/mysql/extra/yassl/taocrypt/src/aes.cpp b/mysql/extra/yassl/taocrypt/src/aes.cpp new file mode 100644 index 0000000..3fcf80a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/aes.cpp @@ -0,0 +1,1885 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* C++ based on Wei Dai's aes.cpp from CryptoPP */ +/* x86 asm original */ + +#if defined(TAOCRYPT_KERNEL_MODE) + #define DO_TAOCRYPT_KERNEL_MODE +#endif // only some modules now support this + +#include "runtime.hpp" +#include "aes.hpp" + + +namespace TaoCrypt { + + +#if defined(DO_AES_ASM) + +// ia32 optimized version +void AES::Process(byte* out, const byte* in, word32 sz) +{ + if (!isMMX) { + Mode_BASE::Process(out, in, sz); + return; + } + + word32 blocks = sz / BLOCK_SIZE; + + if (mode_ == ECB) + while (blocks--) { + if (dir_ == ENCRYPTION) + AsmEncrypt(in, out, (void*)Te0); + else + AsmDecrypt(in, out, (void*)Td0); + out += BLOCK_SIZE; + in += BLOCK_SIZE; + } + else if (mode_ == CBC) { + if (dir_ == ENCRYPTION) { + while (blocks--) { + r_[0] ^= *(word32*)in; + r_[1] ^= *(word32*)(in + 4); + r_[2] ^= *(word32*)(in + 8); + r_[3] ^= *(word32*)(in + 12); + + AsmEncrypt((byte*)r_, (byte*)r_, (void*)Te0); + + memcpy(out, r_, BLOCK_SIZE); + out += BLOCK_SIZE; + in += BLOCK_SIZE; + } + } + else { + while (blocks--) { + AsmDecrypt(in, out, (void*)Td0); + + *(word32*)out ^= r_[0]; + *(word32*)(out + 4) ^= r_[1]; + *(word32*)(out + 8) ^= r_[2]; + *(word32*)(out + 12) ^= r_[3]; + + memcpy(r_, in, BLOCK_SIZE); + out += BLOCK_SIZE; + in += BLOCK_SIZE; + } + } + } +} + +#endif // DO_AES_ASM + + +void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/) +{ + if (keylen <= 16) + keylen = 16; + else if (keylen >= 32) + keylen = 32; + else if (keylen != 24) + keylen = 24; + + rounds_ = keylen/4 + 6; + + word32 temp, *rk = key_; + unsigned int i=0; + + GetUserKey(BigEndianOrder, rk, keylen/4, userKey, keylen); + + switch(keylen) + { + case 16: + while (true) + { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te2[GETBYTE(temp, 2)] & 0xff000000) ^ + (Te3[GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te0[GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te1[GETBYTE(temp, 3)] & 0x000000ff) ^ + rcon_[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) + break; + rk += 4; + } + break; + + case 24: + while (true) // for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack + { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te2[GETBYTE(temp, 2)] & 0xff000000) ^ + (Te3[GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te0[GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te1[GETBYTE(temp, 3)] & 0x000000ff) ^ + rcon_[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) + break; + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + break; + + case 32: + while (true) + { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te2[GETBYTE(temp, 2)] & 0xff000000) ^ + (Te3[GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te0[GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te1[GETBYTE(temp, 3)] & 0x000000ff) ^ + rcon_[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) + break; + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te2[GETBYTE(temp, 3)] & 0xff000000) ^ + (Te3[GETBYTE(temp, 2)] & 0x00ff0000) ^ + (Te0[GETBYTE(temp, 1)] & 0x0000ff00) ^ + (Te1[GETBYTE(temp, 0)] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + break; + } + + if (dir_ == DECRYPTION) + { + unsigned int i, j; + rk = key_; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*rounds_; 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 < rounds_; i++) { + rk += 4; + rk[0] = + Td0[Te1[GETBYTE(rk[0], 3)] & 0xff] ^ + Td1[Te1[GETBYTE(rk[0], 2)] & 0xff] ^ + Td2[Te1[GETBYTE(rk[0], 1)] & 0xff] ^ + Td3[Te1[GETBYTE(rk[0], 0)] & 0xff]; + rk[1] = + Td0[Te1[GETBYTE(rk[1], 3)] & 0xff] ^ + Td1[Te1[GETBYTE(rk[1], 2)] & 0xff] ^ + Td2[Te1[GETBYTE(rk[1], 1)] & 0xff] ^ + Td3[Te1[GETBYTE(rk[1], 0)] & 0xff]; + rk[2] = + Td0[Te1[GETBYTE(rk[2], 3)] & 0xff] ^ + Td1[Te1[GETBYTE(rk[2], 2)] & 0xff] ^ + Td2[Te1[GETBYTE(rk[2], 1)] & 0xff] ^ + Td3[Te1[GETBYTE(rk[2], 0)] & 0xff]; + rk[3] = + Td0[Te1[GETBYTE(rk[3], 3)] & 0xff] ^ + Td1[Te1[GETBYTE(rk[3], 2)] & 0xff] ^ + Td2[Te1[GETBYTE(rk[3], 1)] & 0xff] ^ + Td3[Te1[GETBYTE(rk[3], 0)] & 0xff]; + } + } +} + + +void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const +{ + if (dir_ == ENCRYPTION) + encrypt(in, xOr, out); + else + decrypt(in, xOr, out); +} + + +typedef BlockGetAndPut gpBlock; + + +void AES::encrypt(const byte* inBlock, const byte* xorBlock, + byte* outBlock) const +{ + word32 s0, s1, s2, s3; + word32 t0, t1, t2, t3; + + const word32 *rk = key_; + /* + * map byte array block to cipher state + * and add initial round key: + */ + gpBlock::Get(inBlock)(s0)(s1)(s2)(s3); + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + s0 |= PreFetchTe(); + /* + * Nr - 1 full rounds: + */ + + unsigned int r = rounds_ >> 1; + for (;;) { + t0 = + Te0[GETBYTE(s0, 3)] ^ + Te1[GETBYTE(s1, 2)] ^ + Te2[GETBYTE(s2, 1)] ^ + Te3[GETBYTE(s3, 0)] ^ + rk[4]; + t1 = + Te0[GETBYTE(s1, 3)] ^ + Te1[GETBYTE(s2, 2)] ^ + Te2[GETBYTE(s3, 1)] ^ + Te3[GETBYTE(s0, 0)] ^ + rk[5]; + t2 = + Te0[GETBYTE(s2, 3)] ^ + Te1[GETBYTE(s3, 2)] ^ + Te2[GETBYTE(s0, 1)] ^ + Te3[GETBYTE(s1, 0)] ^ + rk[6]; + t3 = + Te0[GETBYTE(s3, 3)] ^ + Te1[GETBYTE(s0, 2)] ^ + Te2[GETBYTE(s1, 1)] ^ + Te3[GETBYTE(s2, 0)] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[GETBYTE(t0, 3)] ^ + Te1[GETBYTE(t1, 2)] ^ + Te2[GETBYTE(t2, 1)] ^ + Te3[GETBYTE(t3, 0)] ^ + rk[0]; + s1 = + Te0[GETBYTE(t1, 3)] ^ + Te1[GETBYTE(t2, 2)] ^ + Te2[GETBYTE(t3, 1)] ^ + Te3[GETBYTE(t0, 0)] ^ + rk[1]; + s2 = + Te0[GETBYTE(t2, 3)] ^ + Te1[GETBYTE(t3, 2)] ^ + Te2[GETBYTE(t0, 1)] ^ + Te3[GETBYTE(t1, 0)] ^ + rk[2]; + s3 = + Te0[GETBYTE(t3, 3)] ^ + Te1[GETBYTE(t0, 2)] ^ + Te2[GETBYTE(t1, 1)] ^ + Te3[GETBYTE(t2, 0)] ^ + rk[3]; + } + + /* + * apply last round and + * map cipher state to byte array block: + */ + + s0 = + (Te2[GETBYTE(t0, 3)] & 0xff000000) ^ + (Te3[GETBYTE(t1, 2)] & 0x00ff0000) ^ + (Te0[GETBYTE(t2, 1)] & 0x0000ff00) ^ + (Te1[GETBYTE(t3, 0)] & 0x000000ff) ^ + rk[0]; + s1 = + (Te2[GETBYTE(t1, 3)] & 0xff000000) ^ + (Te3[GETBYTE(t2, 2)] & 0x00ff0000) ^ + (Te0[GETBYTE(t3, 1)] & 0x0000ff00) ^ + (Te1[GETBYTE(t0, 0)] & 0x000000ff) ^ + rk[1]; + s2 = + (Te2[GETBYTE(t2, 3)] & 0xff000000) ^ + (Te3[GETBYTE(t3, 2)] & 0x00ff0000) ^ + (Te0[GETBYTE(t0, 1)] & 0x0000ff00) ^ + (Te1[GETBYTE(t1, 0)] & 0x000000ff) ^ + rk[2]; + s3 = + (Te2[GETBYTE(t3, 3)] & 0xff000000) ^ + (Te3[GETBYTE(t0, 2)] & 0x00ff0000) ^ + (Te0[GETBYTE(t1, 1)] & 0x0000ff00) ^ + (Te1[GETBYTE(t2, 0)] & 0x000000ff) ^ + rk[3]; + + + gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3); +} + + +void AES::decrypt(const byte* inBlock, const byte* xorBlock, + byte* outBlock) const +{ + word32 s0, s1, s2, s3; + word32 t0, t1, t2, t3; + const word32* rk = key_; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + gpBlock::Get(inBlock)(s0)(s1)(s2)(s3); + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + s0 |= PreFetchTd(); + + /* + * Nr - 1 full rounds: + */ + + unsigned int r = rounds_ >> 1; + for (;;) { + t0 = + Td0[GETBYTE(s0, 3)] ^ + Td1[GETBYTE(s3, 2)] ^ + Td2[GETBYTE(s2, 1)] ^ + Td3[GETBYTE(s1, 0)] ^ + rk[4]; + t1 = + Td0[GETBYTE(s1, 3)] ^ + Td1[GETBYTE(s0, 2)] ^ + Td2[GETBYTE(s3, 1)] ^ + Td3[GETBYTE(s2, 0)] ^ + rk[5]; + t2 = + Td0[GETBYTE(s2, 3)] ^ + Td1[GETBYTE(s1, 2)] ^ + Td2[GETBYTE(s0, 1)] ^ + Td3[GETBYTE(s3, 0)] ^ + rk[6]; + t3 = + Td0[GETBYTE(s3, 3)] ^ + Td1[GETBYTE(s2, 2)] ^ + Td2[GETBYTE(s1, 1)] ^ + Td3[GETBYTE(s0, 0)] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[GETBYTE(t0, 3)] ^ + Td1[GETBYTE(t3, 2)] ^ + Td2[GETBYTE(t2, 1)] ^ + Td3[GETBYTE(t1, 0)] ^ + rk[0]; + s1 = + Td0[GETBYTE(t1, 3)] ^ + Td1[GETBYTE(t0, 2)] ^ + Td2[GETBYTE(t3, 1)] ^ + Td3[GETBYTE(t2, 0)] ^ + rk[1]; + s2 = + Td0[GETBYTE(t2, 3)] ^ + Td1[GETBYTE(t1, 2)] ^ + Td2[GETBYTE(t0, 1)] ^ + Td3[GETBYTE(t3, 0)] ^ + rk[2]; + s3 = + Td0[GETBYTE(t3, 3)] ^ + Td1[GETBYTE(t2, 2)] ^ + Td2[GETBYTE(t1, 1)] ^ + Td3[GETBYTE(t0, 0)] ^ + rk[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + + t0 |= PreFetchCTd4(); + + s0 = + ((word32)CTd4[GETBYTE(t0, 3)] << 24) ^ + ((word32)CTd4[GETBYTE(t3, 2)] << 16) ^ + ((word32)CTd4[GETBYTE(t2, 1)] << 8) ^ + ((word32)CTd4[GETBYTE(t1, 0)]) ^ + rk[0]; + s1 = + ((word32)CTd4[GETBYTE(t1, 3)] << 24) ^ + ((word32)CTd4[GETBYTE(t0, 2)] << 16) ^ + ((word32)CTd4[GETBYTE(t3, 1)] << 8) ^ + ((word32)CTd4[GETBYTE(t2, 0)]) ^ + rk[1]; + s2 = + ((word32)CTd4[GETBYTE(t2, 3)] << 24 ) ^ + ((word32)CTd4[GETBYTE(t1, 2)] << 16 ) ^ + ((word32)CTd4[GETBYTE(t0, 1)] << 8 ) ^ + ((word32)CTd4[GETBYTE(t3, 0)]) ^ + rk[2]; + s3 = + ((word32)CTd4[GETBYTE(t3, 3)] << 24) ^ + ((word32)CTd4[GETBYTE(t2, 2)] << 16) ^ + ((word32)CTd4[GETBYTE(t1, 1)] << 8) ^ + ((word32)CTd4[GETBYTE(t0, 0)]) ^ + rk[3]; + + gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3); +} + + +#if defined(DO_AES_ASM) + #ifdef __GNUC__ + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + + #define PROLOG() \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + "push ebx;" \ + "push ebp;" \ + "movd mm7, ebp;" \ + "movd mm4, eax;" \ + "mov ebp, edx;" \ + "sub esp, 4;" + #define EPILOG() \ + "add esp, 4;" \ + "pop ebp;" \ + "pop ebx;" \ + "emms;" \ + ".att_syntax;" \ + : \ + : "c" (this), "S" (inBlock), "d" (boxes), "a" (outBlock) \ + : "%edi", "memory", "cc" \ + ); + + #else + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + + #define PROLOG() \ + AS1( push ebp ) \ + AS2( mov ebp, esp ) \ + AS2( movd mm3, edi ) \ + AS2( movd mm4, ebx ) \ + AS2( sub esp, 4 ) \ + AS2( movd mm7, ebp ) \ + AS2( mov [ebp - 4], esi ) \ + AS2( mov esi, DWORD PTR [ebp + 8] ) \ + AS2( mov ebp, DWORD PTR [ebp + 16] ) + + // ebp is restored at end + #define EPILOG() \ + AS2( mov esi, [ebp - 4] ) \ + AS2( movd ebx, mm4 ) \ + AS2( movd edi, mm3 ) \ + AS2( mov esp, ebp ) \ + AS1( pop ebp ) \ + AS1( emms ) \ + AS1( ret 12 ) + + + #endif + + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void AES::AsmEncrypt(const byte* inBlock, byte* outBlock, void* boxes) const +{ + + PROLOG() + + #ifdef OLD_GCC_OFFSET + AS2( mov edx, DWORD PTR [ecx + 60] ) // rounds + AS2( lea edi, [ecx + 64] ) // rk + #else + AS2( mov edx, DWORD PTR [ecx + 56] ) // rounds + AS2( lea edi, [ecx + 60] ) // rk + #endif + + AS1( dec edx ) + AS2( movd mm6, edi ) // save rk + AS2( movd mm5, edx ) // save rounds + + AS2( mov eax, DWORD PTR [esi] ) + AS2( mov ebx, DWORD PTR [esi + 4] ) + AS2( mov ecx, DWORD PTR [esi + 8] ) + AS2( mov edx, DWORD PTR [esi + 12] ) + + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( xor eax, DWORD PTR [edi] ) // s0 + AS2( xor ebx, DWORD PTR [edi + 4] ) // s1 + AS2( xor ecx, DWORD PTR [edi + 8] ) // s2 + AS2( xor edx, DWORD PTR [edi + 12] ) // s3 + +#ifdef _MSC_VER + AS1( loop1: ) // loop1 +#else + AS1(1: ) // loop1 +#endif + /* Put0 (mm0) = + Te0[get0,rs 24] ^ + Te1[get1,rs 16] ^ + Te2[get2,rs 8] ^ + Te3[get3,rs 0] + */ + + AS2( mov esi, eax ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, ebx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx edi, ch ) + AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] ) + + AS2( movzx edi, dl ) + AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] ) + + AS2( movd mm0, esi ) + + /* Put1 (mm1) = + Te0[get1,rs 24] ^ + Te1[get2,rs 16] ^ + Te2[get3,rs 8] ^ + Te3[get0,rs 0] + */ + + AS2( mov esi, ebx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, ecx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx edi, dh ) + AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] ) + + AS2( movzx edi, al ) + AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] ) + + AS2( movd mm1, esi ) + + + /* Put2 (mm2) = + Te0[get2,rs 24] ^ + Te1[get3,rs 16] ^ + Te2[get0,rs 8] ^ + Te3[get1,rs 0] + */ + + AS2( mov esi, ecx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, edx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx edi, ah ) + AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] ) + + AS2( movzx edi, bl ) + AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] ) + + AS2( movd mm2, esi ) + + /* Put3 (edx) = + Te0[get3,rs 24] ^ + Te1[get0,rs 16] ^ + Te2[get1,rs 8] ^ + Te3[get2,rs 0] + */ + + AS2( mov esi, edx ) + AS2( shr esi, 24 ) + AS2( mov edx, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, eax ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor edx, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx esi, bh ) + AS2( xor edx, DWORD PTR [ebp + 2048 + esi*4] ) + + AS2( movzx edi, cl ) + AS2( xor edx, DWORD PTR [ebp + 3072 + edi*4] ) + + // xOr + + AS2( movd esi, mm6 ) // rk + + AS2( movd eax, mm0 ) + AS2( add esi, 16 ) + AS2( movd ebx, mm1 ) + AS2( movd mm6, esi ) // save back + AS2( movd ecx, mm2 ) + + AS2( xor eax, DWORD PTR [esi] ) + AS2( xor ebx, DWORD PTR [esi + 4] ) + AS2( movd edi, mm5 ) + AS2( xor ecx, DWORD PTR [esi + 8] ) + AS2( xor edx, DWORD PTR [esi + 12] ) + + AS1( dec edi ) + AS2( movd mm5, edi ) + +#ifdef _MSC_VER + AS1( jnz loop1) // loop1 +#else + AS1( jnz 1b ) // loop1 +#endif + + // last round + /* + Put0 (mm0) = + (Te4[get0, rs24] & 0xff000000) ^ h = 4278190080 + (Te4[get1, rs16] & 0x00ff0000) ^ h = 16711680 + (Te4[get2, rs 8] & 0x0000ff00) ^ h = 65280 + (Te4[get3, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, eax ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and esi, 4278190080 ) + + AS2( mov edi, ebx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 16711680 ) + AS2( xor esi, edi ) + + AS2( movzx edi, ch ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 65280 ) + AS2( xor esi, edi ) + + AS2( movzx edi, dl ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 255 ) + AS2( xor esi, edi ) + + AS2( movd mm0, esi ) + + /* + Put1 (mm1) = + (Te4[get1, rs24] & 0xff000000) ^ h = 4278190080 + (Te4[get2, rs16] & 0x00ff0000) ^ h = 16711680 + (Te4[get3, rs 8] & 0x0000ff00) ^ h = 65280 + (Te4[get0, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, ebx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and esi, 4278190080 ) + + AS2( mov edi, ecx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 16711680 ) + AS2( xor esi, edi ) + + AS2( movzx edi, dh ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 65280 ) + AS2( xor esi, edi ) + + AS2( movzx edi, al ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 255 ) + AS2( xor esi, edi ) + + AS2( movd mm1, esi ) + + /* + Put2 (mm2) = + (Te4[get2, rs24] & 0xff000000) ^ h = 4278190080 + (Te4[get3, rs16] & 0x00ff0000) ^ h = 16711680 + (Te4[get0, rs 8] & 0x0000ff00) ^ h = 65280 + (Te4[get1, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, ecx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and esi, 4278190080 ) + + AS2( mov edi, edx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 16711680 ) + AS2( xor esi, edi ) + + AS2( movzx edi, ah ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 65280 ) + AS2( xor esi, edi ) + + AS2( movzx edi, bl ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 255 ) + AS2( xor esi, edi ) + + AS2( movd mm2, esi ) + + /* + Put3 (edx) = + (Te4[get3, rs24] & 0xff000000) ^ h = 4278190080 + (Te4[get0, rs16] & 0x00ff0000) ^ h = 16711680 + (Te4[get1, rs 8] & 0x0000ff00) ^ h = 65280 + (Te4[get2, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, edx ) + AS2( shr esi, 24 ) + AS2( mov edx, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and edx, 4278190080 ) + + AS2( mov edi, eax ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and esi, 16711680 ) + AS2( xor edx, esi ) + + AS2( movzx esi, bh ) + AS2( mov edi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and edi, 65280 ) + AS2( xor edx, edi ) + + AS2( movzx edi, cl ) + AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and esi, 255 ) + AS2( xor edx, esi ) + + + // xOr + AS2( movd eax, mm0 ) + AS2( movd esi, mm6 ) // rk + AS2( movd ebx, mm1 ) + AS2( add esi, 16 ) + AS2( movd ecx, mm2 ) + + AS2( xor eax, DWORD PTR [esi] ) + AS2( xor ebx, DWORD PTR [esi + 4] ) + AS2( xor ecx, DWORD PTR [esi + 8] ) + AS2( xor edx, DWORD PTR [esi + 12] ) + + // end + AS2( movd ebp, mm7 ) + + // swap + AS1( bswap eax ) + AS1( bswap ebx ) + + // store + #ifdef __GNUC__ + AS2( movd esi, mm4 ) // outBlock + #else + AS2( mov esi, DWORD PTR [ebp + 12] ) // outBlock + #endif + + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( mov DWORD PTR [esi], eax ) + AS2( mov DWORD PTR [esi + 4], ebx ) + AS2( mov DWORD PTR [esi + 8], ecx ) + AS2( mov DWORD PTR [esi + 12], edx ) + + + EPILOG() +} + + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void AES::AsmDecrypt(const byte* inBlock, byte* outBlock, void* boxes) const +{ + + PROLOG() + + #ifdef OLD_GCC_OFFSET + AS2( mov edx, DWORD PTR [ecx + 60] ) // rounds + AS2( lea edi, [ecx + 64] ) // rk + #else + AS2( mov edx, DWORD PTR [ecx + 56] ) // rounds + AS2( lea edi, [ecx + 60] ) // rk + #endif + + AS1( dec edx ) + AS2( movd mm6, edi ) // save rk + AS2( movd mm5, edx ) // save rounds + + AS2( mov eax, DWORD PTR [esi] ) + AS2( mov ebx, DWORD PTR [esi + 4] ) + AS2( mov ecx, DWORD PTR [esi + 8] ) + AS2( mov edx, DWORD PTR [esi + 12] ) + + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( xor eax, DWORD PTR [edi] ) // s0 + AS2( xor ebx, DWORD PTR [edi + 4] ) // s1 + AS2( xor ecx, DWORD PTR [edi + 8] ) // s2 + AS2( xor edx, DWORD PTR [edi + 12] ) // s3 + + +#ifdef _MSC_VER + AS1( loop2: ) // loop2 +#else + AS1(2: ) // loop2 +#endif + /* Put0 (mm0) = + Td0[GETBYTE(get0, rs24)] ^ + Td1[GETBYTE(get3, rs16)] ^ + Td2[GETBYTE(get2, rs 8)] ^ + Td3[GETBYTE(tet1, )] + */ + AS2( mov esi, eax ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, edx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx edi, ch ) + AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] ) + + AS2( movzx edi, bl ) + AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] ) + + AS2( movd mm0, esi ) + + /* Put1 (mm1) = + Td0[GETBYTE(get1, rs24)] ^ + Td1[GETBYTE(get0, rs16)] ^ + Td2[GETBYTE(get3, rs 8)] ^ + Td3[GETBYTE(tet2, )] + */ + AS2( mov esi, ebx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, eax ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx edi, dh ) + AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] ) + + AS2( movzx edi, cl ) + AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] ) + + AS2( movd mm1, esi ) + + /* Put2 (mm2) = + Td0[GETBYTE(get2, rs24)] ^ + Td1[GETBYTE(get1, rs16)] ^ + Td2[GETBYTE(get0, rs 8)] ^ + Td3[GETBYTE(tet3, )] + */ + AS2( mov esi, ecx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, ebx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor esi, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx edi, ah ) + AS2( xor esi, DWORD PTR [ebp + 2048 + edi*4] ) + + AS2( movzx edi, dl ) + AS2( xor esi, DWORD PTR [ebp + 3072 + edi*4] ) + + AS2( movd mm2, esi ) + + /* Put3 (edx) = + Td0[GETBYTE(get3, rs24)] ^ + Td1[GETBYTE(get2, rs16)] ^ + Td2[GETBYTE(get1, rs 8)] ^ + Td3[GETBYTE(tet0, )] + */ + AS2( mov esi, edx ) + AS2( shr esi, 24 ) + AS2( mov edx, DWORD PTR [ebp + esi*4] ) + + AS2( mov edi, ecx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( xor edx, DWORD PTR [ebp + 1024 + edi*4] ) + + AS2( movzx esi, bh ) + AS2( xor edx, DWORD PTR [ebp + 2048 + esi*4] ) + + AS2( movzx edi, al ) + AS2( xor edx, DWORD PTR [ebp + 3072 + edi*4] ) + + + // xOr + + AS2( movd esi, mm6 ) // rk + AS2( add esi, 16 ) + AS2( movd mm6, esi ) // save back + + AS2( movd eax, mm0 ) + AS2( movd ebx, mm1 ) + AS2( movd ecx, mm2 ) + + AS2( xor eax, DWORD PTR [esi] ) + AS2( xor ebx, DWORD PTR [esi + 4] ) + AS2( xor ecx, DWORD PTR [esi + 8] ) + AS2( xor edx, DWORD PTR [esi + 12] ) + + AS2( movd edi, mm5 ) + AS1( dec edi ) + AS2( movd mm5, edi ) + +#ifdef _MSC_VER + AS1( jnz loop2) // loop2 +#else + AS1( jnz 2b ) // loop2 +#endif + + // last round + /* + Put0 (mm0) = + (Td4[get0, rs24] & 0xff000000) ^ h = 4278190080 + (Td4[get3, rs16] & 0x00ff0000) ^ h = 16711680 + (Td4[get2, rs 8] & 0x0000ff00) ^ h = 65280 + (Td4[get1, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, eax ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and esi, 4278190080 ) + + AS2( mov edi, edx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 16711680 ) + AS2( xor esi, edi ) + + AS2( movzx edi, ch ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 65280 ) + AS2( xor esi, edi ) + + AS2( movzx edi, bl ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 255 ) + AS2( xor esi, edi ) + + AS2( movd mm0, esi ) + + /* + Put1 (mm1) = + (Td4[get1, rs24] & 0xff000000) ^ h = 4278190080 + (Td4[get0, rs16] & 0x00ff0000) ^ h = 16711680 + (Td4[get3, rs 8] & 0x0000ff00) ^ h = 65280 + (Td4[get2, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, ebx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and esi, 4278190080 ) + + AS2( mov edi, eax ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 16711680 ) + AS2( xor esi, edi ) + + AS2( movzx edi, dh ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 65280 ) + AS2( xor esi, edi ) + + AS2( movzx edi, cl ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 255 ) + AS2( xor esi, edi ) + + AS2( movd mm1, esi ) + + /* + Put2 (mm2) = + (Td4[get2, rs24] & 0xff000000) ^ h = 4278190080 + (Td4[get1, rs16] & 0x00ff0000) ^ h = 16711680 + (Td4[get0, rs 8] & 0x0000ff00) ^ h = 65280 + (Td4[get3, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, ecx ) + AS2( shr esi, 24 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and esi, 4278190080 ) + + AS2( mov edi, ebx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 16711680 ) + AS2( xor esi, edi ) + + AS2( movzx edi, ah ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 65280 ) + AS2( xor esi, edi ) + + AS2( movzx edi, dl ) + AS2( mov edi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and edi, 255 ) + AS2( xor esi, edi ) + + AS2( movd mm2, esi ) + + /* + Put3 (edx) = + (Td4[get3, rs24] & 0xff000000) ^ h = 4278190080 + (Td4[get2, rs16] & 0x00ff0000) ^ h = 16711680 + (Td4[get1, rs 8] & 0x0000ff00) ^ h = 65280 + (Td4[get0, rs 0] & 0x000000ff) h = 255 + */ + AS2( mov esi, edx ) + AS2( shr esi, 24 ) + AS2( mov edx, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and edx, 4278190080 ) + + AS2( mov edi, ecx ) + AS2( shr edi, 16 ) + AS2( and edi, 255 ) + AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and esi, 16711680 ) + AS2( xor edx, esi ) + + AS2( movzx esi, bh ) + AS2( mov edi, DWORD PTR [ebp + 4096 + esi*4] ) + AS2( and edi, 65280 ) + AS2( xor edx, edi ) + + AS2( movzx edi, al ) + AS2( mov esi, DWORD PTR [ebp + 4096 + edi*4] ) + AS2( and esi, 255 ) + AS2( xor edx, esi ) + + + // xOr + AS2( movd esi, mm6 ) // rk + AS2( add esi, 16 ) + + AS2( movd eax, mm0 ) + AS2( movd ebx, mm1 ) + AS2( movd ecx, mm2 ) + + AS2( xor eax, DWORD PTR [esi] ) + AS2( xor ebx, DWORD PTR [esi + 4] ) + AS2( xor ecx, DWORD PTR [esi + 8] ) + AS2( xor edx, DWORD PTR [esi + 12] ) + + // end + AS2( movd ebp, mm7 ) + + // swap + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + // store + #ifdef __GNUC__ + AS2( movd esi, mm4 ) // outBlock + #else + AS2( mov esi, DWORD PTR [ebp + 12] ) // outBlock + #endif + AS2( mov DWORD PTR [esi], eax ) + AS2( mov DWORD PTR [esi + 4], ebx ) + AS2( mov DWORD PTR [esi + 8], ecx ) + AS2( mov DWORD PTR [esi + 12], edx ) + + + EPILOG() +} + + + +#endif // defined(DO_AES_ASM) + + + +const word32 AES::Te[5][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, +}, +{ + 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, +}, +{ + 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, +}, +{ + 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, +}, +{ + 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, +} +}; + + +const word32 AES::Td[5][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, +}, +{ + 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, +}, +{ + 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, +}, +{ + 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, +}, +{ + 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, +} +}; + +const byte AES::CTd4[256] = +{ + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; + + +const word32* AES::Te0 = AES::Te[0]; +const word32* AES::Te1 = AES::Te[1]; +const word32* AES::Te2 = AES::Te[2]; +const word32* AES::Te3 = AES::Te[3]; + +const word32* AES::Td0 = AES::Td[0]; +const word32* AES::Td1 = AES::Td[1]; +const word32* AES::Td2 = AES::Td[2]; +const word32* AES::Td3 = AES::Td[3]; + + + +} // namespace + diff --git a/mysql/extra/yassl/taocrypt/src/aestables.cpp b/mysql/extra/yassl/taocrypt/src/aestables.cpp new file mode 100644 index 0000000..60795a5 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/aestables.cpp @@ -0,0 +1,36 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's aestables.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "aes.hpp" + + +namespace TaoCrypt { + + +const word32 AES::rcon_[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/algebra.cpp b/mysql/extra/yassl/taocrypt/src/algebra.cpp new file mode 100644 index 0000000..ace1704 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/algebra.cpp @@ -0,0 +1,336 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +/* based on Wei Dai's algebra.cpp from CryptoPP */ +#undef NDEBUG +#define DEBUG // GCC 4.0 bug if NDEBUG and Optimize > 1 + +#include "runtime.hpp" +#include "algebra.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "vector.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + +namespace TaoCrypt { + + +const Integer& AbstractGroup::Double(const Element &a) const +{ + return Add(a, a); +} + +const Integer& AbstractGroup::Subtract(const Element &a, const Element &b) const +{ + // make copy of a in case Inverse() overwrites it + Element a1(a); + return Add(a1, Inverse(b)); +} + +Integer& AbstractGroup::Accumulate(Element &a, const Element &b) const +{ + return a = Add(a, b); +} + +Integer& AbstractGroup::Reduce(Element &a, const Element &b) const +{ + return a = Subtract(a, b); +} + +const Integer& AbstractRing::Square(const Element &a) const +{ + return Multiply(a, a); +} + + +const Integer& AbstractRing::Divide(const Element &a, const Element &b) const +{ + // make copy of a in case MultiplicativeInverse() overwrites it + Element a1(a); + return Multiply(a1, MultiplicativeInverse(b)); +} + + +const Integer& AbstractEuclideanDomain::Mod(const Element &a, + const Element &b) const +{ + Element q; + DivisionAlgorithm(result, q, a, b); + return result; +} + +const Integer& AbstractEuclideanDomain::Gcd(const Element &a, + const Element &b) const +{ + STL::vector g(3); + g[0]= b; + g[1]= a; + unsigned int i0=0, i1=1, i2=2; + + while (!Equal(g[i1], this->Identity())) + { + g[i2] = Mod(g[i0], g[i1]); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return result = g[i0]; +} + + +Integer AbstractGroup::ScalarMultiply(const Element &base, + const Integer &exponent) const +{ + Element result; + SimultaneousMultiply(&result, base, &exponent, 1); + return result; +} + + +Integer AbstractGroup::CascadeScalarMultiply(const Element &x, + const Integer &e1, const Element &y, const Integer &e2) const +{ + const unsigned expLen = max(e1.BitCount(), e2.BitCount()); + if (expLen==0) + return Identity(); + + const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); + const unsigned tableSize = 1< powerTable(tableSize << w); + + powerTable[1] = x; + powerTable[tableSize] = y; + if (w==1) + powerTable[3] = Add(x,y); + else + { + powerTable[2] = Double(x); + powerTable[2*tableSize] = Double(y); + + unsigned i, j; + + for (i=3; i=0; i--) + { + power1 = 2*power1 + e1.GetBit(i); + power2 = 2*power2 + e2.GetBit(i); + + if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) + { + unsigned squaresBefore = prevPosition-i; + unsigned squaresAfter = 0; + prevPosition = i; + while ((power1 || power2) && power1%2 == 0 && power2%2==0) + { + power1 /= 2; + power2 /= 2; + squaresBefore--; + squaresAfter++; + } + if (firstTime) + { + result = powerTable[(power2<= expLen) + { + finished = true; + return; + } + skipCount++; + } + + exp >>= skipCount; + windowBegin += skipCount; + expWindow = exp % (1 << windowSize); + + if (fastNegate && exp.GetBit(windowSize)) + { + negateNext = true; + expWindow = (1 << windowSize) - expWindow; + exp += windowModulus; + } + else + negateNext = false; + } + + Integer exp, windowModulus; + unsigned int windowSize, windowBegin, expWindow; + bool fastNegate, negateNext, firstTime, finished; +}; + + +void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base, + const Integer *expBegin, unsigned int expCount) const +{ + STL::vector > buckets(expCount); + STL::vector exponents; + exponents.reserve(expCount); + unsigned int i; + + for (i=0; i 1) + { + for (size_t j = buckets[i].size()-2; j >= 1; j--) + { + Accumulate(buckets[i][j], buckets[i][j+1]); + Accumulate(r, buckets[i][j]); + } + Accumulate(buckets[i][0], buckets[i][1]); + r = Add(Double(r), buckets[i][0]); + } + } +} + +Integer AbstractRing::Exponentiate(const Element &base, + const Integer &exponent) const +{ + Element result; + SimultaneousExponentiate(&result, base, &exponent, 1); + return result; +} + + +Integer AbstractRing::CascadeExponentiate(const Element &x, + const Integer &e1, const Element &y, const Integer &e2) const +{ + return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply( + x, e1, y, e2); +} + + +void AbstractRing::SimultaneousExponentiate(Integer *results, + const Integer &base, + const Integer *exponents, unsigned int expCount) const +{ + MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base, + exponents, expCount); +} + + +} // namespace + + +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION +namespace mySTL { +template TaoCrypt::WindowSlider* uninit_copy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); +template void destroy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); +template TaoCrypt::WindowSlider* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::WindowSlider*); +} +#endif + diff --git a/mysql/extra/yassl/taocrypt/src/arc4.cpp b/mysql/extra/yassl/taocrypt/src/arc4.cpp new file mode 100644 index 0000000..10a3a7d --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/arc4.cpp @@ -0,0 +1,243 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's arc4.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "arc4.hpp" + + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_ARC4_ASM +#endif + + +namespace TaoCrypt { + +void ARC4::SetKey(const byte* key, word32 length) +{ + x_ = 1; + y_ = 0; + + word32 i; + + for (i = 0; i < STATE_SIZE; i++) + state_[i] = i; + + word32 keyIndex = 0, stateIndex = 0; + + for (i = 0; i < STATE_SIZE; i++) { + word32 a = state_[i]; + stateIndex += key[keyIndex] + a; + stateIndex &= 0xFF; + state_[i] = state_[stateIndex]; + state_[stateIndex] = a; + + if (++keyIndex >= length) + keyIndex = 0; + } +} + + +// local +namespace { + +inline unsigned int MakeByte(word32& x, word32& y, byte* s) +{ + word32 a = s[x]; + y = (y+a) & 0xff; + + word32 b = s[y]; + s[x] = b; + s[y] = a; + x = (x+1) & 0xff; + + return s[(a+b) & 0xff]; +} + +} // namespace + + + +void ARC4::Process(byte* out, const byte* in, word32 length) +{ + if (length == 0) return; + +#ifdef DO_ARC4_ASM + if (isMMX) { + AsmProcess(out, in, length); + return; + } +#endif + + byte *const s = state_; + word32 x = x_; + word32 y = y_; + + if (in == out) + while (length--) + *out++ ^= MakeByte(x, y, s); + else + while(length--) + *out++ = *in++ ^ MakeByte(x, y, s); + x_ = x; + y_ = y; +} + + + +#ifdef DO_ARC4_ASM + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void ARC4::AsmProcess(byte* out, const byte* in, word32 length) +{ +#ifdef __GNUC__ + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + + #define PROLOG() \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + "push ebx;" \ + "push ebp;" \ + "mov ebp, eax;" + #define EPILOG() \ + "pop ebp;" \ + "pop ebx;" \ + "emms;" \ + ".att_syntax;" \ + : \ + : "c" (this), "D" (out), "S" (in), "a" (length) \ + : "%edx", "memory", "cc" \ + ); + +#else + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + + #define PROLOG() \ + AS1( push ebp ) \ + AS2( mov ebp, esp ) \ + AS2( movd mm3, edi ) \ + AS2( movd mm4, ebx ) \ + AS2( movd mm5, esi ) \ + AS2( movd mm6, ebp ) \ + AS2( mov edi, DWORD PTR [ebp + 8] ) \ + AS2( mov esi, DWORD PTR [ebp + 12] ) \ + AS2( mov ebp, DWORD PTR [ebp + 16] ) + + #define EPILOG() \ + AS2( movd ebp, mm6 ) \ + AS2( movd esi, mm5 ) \ + AS2( movd ebx, mm4 ) \ + AS2( movd edi, mm3 ) \ + AS2( mov esp, ebp ) \ + AS1( pop ebp ) \ + AS1( emms ) \ + AS1( ret 12 ) + +#endif + + PROLOG() + + AS2( sub esp, 4 ) // make room + + AS2( cmp ebp, 0 ) + AS1( jz nothing ) + + AS2( mov [esp], ebp ) // length + + AS2( movzx edx, BYTE PTR [ecx + 1] ) // y + AS2( lea ebp, [ecx + 2] ) // state_ + AS2( movzx ecx, BYTE PTR [ecx] ) // x + + // setup loop + // a = s[x]; + AS2( movzx eax, BYTE PTR [ebp + ecx] ) + + +#ifdef _MSC_VER + AS1( loopStart: ) // loopStart +#else + AS1( 0: ) // loopStart for some gas (need numeric for jump back +#endif + + // y = (y+a) & 0xff; + AS2( add edx, eax ) + AS2( and edx, 255 ) + + // b = s[y]; + AS2( movzx ebx, BYTE PTR [ebp + edx] ) + + // s[x] = b; + AS2( mov [ebp + ecx], bl ) + + // s[y] = a; + AS2( mov [ebp + edx], al ) + + // x = (x+1) & 0xff; + AS1( inc ecx ) + AS2( and ecx, 255 ) + + //return s[(a+b) & 0xff]; + AS2( add eax, ebx ) + AS2( and eax, 255 ) + + AS2( movzx ebx, BYTE PTR [ebp + eax] ) + + // a = s[x]; for next round + AS2( movzx eax, BYTE PTR [ebp + ecx] ) + + // xOr w/ inByte + AS2( xor bl, BYTE PTR [esi] ) + AS1( inc esi ) + + // write to outByte + AS2( mov [edi], bl ) + AS1( inc edi ) + + AS1( dec DWORD PTR [esp] ) +#ifdef _MSC_VER + AS1( jnz loopStart ) // loopStart +#else + AS1( jnz 0b ) // loopStart +#endif + + + // write back to x_ and y_ + AS2( mov [ebp - 2], cl ) + AS2( mov [ebp - 1], dl ) + + +AS1( nothing: ) + + // inline adjust + AS2( add esp, 4 ) // fix room on stack + + EPILOG() +} + +#endif // DO_ARC4_ASM + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/asn.cpp b/mysql/extra/yassl/taocrypt/src/asn.cpp new file mode 100644 index 0000000..e0aef45 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/asn.cpp @@ -0,0 +1,1348 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* asn.cpp implements ASN1 BER, PublicKey, and x509v3 decoding +*/ + +#include "runtime.hpp" +#include "asn.hpp" +#include "file.hpp" +#include "integer.hpp" +#include "rsa.hpp" +#include "dsa.hpp" +#include "dh.hpp" +#include "md5.hpp" +#include "md2.hpp" +#include "sha.hpp" +#include "coding.hpp" +#include // gmtime(); +#include "memory.hpp" // some auto_ptr don't have reset, also need auto_array + + +namespace TaoCrypt { + +// like atoi but only use first byte +word32 btoi(byte b) +{ + return b - 0x30; +} + + +// two byte date/time, add to value +void GetTime(int *value, const byte* date, int& i) +{ + *value += btoi(date[i++]) * 10; + *value += btoi(date[i++]); +} + + +bool ASN1_TIME_extract(const unsigned char* date, unsigned char format, + tm *t) +{ + int i = 0; + memset(t, 0, sizeof (tm)); + + if (format != UTC_TIME && format != GENERALIZED_TIME) + return false; + + if (format == UTC_TIME) { + if (btoi(date[0]) >= 5) + t->tm_year = 1900; + else + t->tm_year = 2000; + } + else { // format == GENERALIZED_TIME + t->tm_year += btoi(date[i++]) * 1000; + t->tm_year += btoi(date[i++]) * 100; + } + + GetTime(&t->tm_year, date, i); t->tm_year -= 1900; // adjust + GetTime(&t->tm_mon, date, i); t->tm_mon -= 1; // adjust + GetTime(&t->tm_mday, date, i); + GetTime(&t->tm_hour, date, i); + GetTime(&t->tm_min, date, i); + GetTime(&t->tm_sec, date, i); + + if (date[i] != 'Z') // only Zulu supported for this profile + return false; + return true; +} + + +namespace { // locals + + +// to the second +bool operator>(tm& a, tm& b) +{ + if (a.tm_year > b.tm_year) + return true; + + if (a.tm_year == b.tm_year && a.tm_mon > b.tm_mon) + return true; + + if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && a.tm_mday >b.tm_mday) + return true; + + if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && + a.tm_mday == b.tm_mday && a.tm_hour > b.tm_hour) + return true; + + if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && + a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour && + a.tm_min > b.tm_min) + return true; + + if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && + a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour && + a.tm_min == b.tm_min && a.tm_sec > b.tm_sec) + return true; + + return false; +} + + +bool operator<(tm& a, tm&b) +{ + return (b>a); +} + + +// Make sure before and after dates are valid +bool ValidateDate(const byte* date, byte format, CertDecoder::DateType dt) +{ + tm certTime; + + if (!ASN1_TIME_extract(date, format, &certTime)) + return false; + + time_t ltime = time(0); + tm* localTime = gmtime(<ime); + + if (dt == CertDecoder::BEFORE) { + if (*localTime < certTime) + return false; + } + else + if (*localTime > certTime) + return false; + + return true; +} + + +class BadCertificate {}; + +} // local namespace + + + +// used by Integer as well +word32 GetLength(Source& source) +{ + word32 length = 0; + + byte b = source.next(); + if (b >= LONG_LENGTH) { + word32 bytes = b & 0x7F; + + if (source.IsLeft(bytes) == false) return 0; + + while (bytes--) { + b = source.next(); + length = (length << 8) | b; + } + } + else + length = b; + + if (source.IsLeft(length) == false) return 0; + + return length; +} + + +word32 SetLength(word32 length, byte* output) +{ + word32 i = 0; + + if (length < LONG_LENGTH) + output[i++] = length; + else { + output[i++] = BytePrecision(length) | 0x80; + + for (int j = BytePrecision(length); j; --j) { + output[i] = length >> (j - 1) * 8; + i++; + } + } + return i; +} + + +PublicKey::PublicKey(const byte* k, word32 s) : key_(0), sz_(0) +{ + if (s) { + SetSize(s); + SetKey(k); + } +} + + +void PublicKey::SetSize(word32 s) +{ + sz_ = s; + key_ = NEW_TC byte[sz_]; +} + + +void PublicKey::SetKey(const byte* k) +{ + memcpy(key_, k, sz_); +} + + +void PublicKey::AddToEnd(const byte* data, word32 len) +{ + mySTL::auto_array tmp(NEW_TC byte[sz_ + len]); + + memcpy(tmp.get(), key_, sz_); + memcpy(tmp.get() + sz_, data, len); + + byte* del = 0; + STL::swap(del, key_); + tcArrayDelete(del); + + key_ = tmp.release(); + sz_ += len; +} + + +Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h) + : key_(k, kSz) +{ + size_t sz = strlen(n); + memcpy(name_, n, sz); + name_[sz] = 0; + + memcpy(hash_, h, SHA::DIGEST_SIZE); +} + +Signer::~Signer() +{ +} + + +Error BER_Decoder::GetError() +{ + return source_.GetError(); +} + + +Integer& BER_Decoder::GetInteger(Integer& integer) +{ + if (!source_.GetError().What()) + integer.Decode(source_); + return integer; +} + + +// Read a Sequence, return length +word32 BER_Decoder::GetSequence() +{ + if (source_.GetError().What()) return 0; + + byte b = source_.next(); + if (b != (SEQUENCE | CONSTRUCTED)) { + source_.SetError(SEQUENCE_E); + return 0; + } + + return GetLength(source_); +} + + +// Read a Sequence, return length +word32 BER_Decoder::GetSet() +{ + if (source_.GetError().What()) return 0; + + byte b = source_.next(); + if (b != (SET | CONSTRUCTED)) { + source_.SetError(SET_E); + return 0; + } + + return GetLength(source_); +} + + +// Read Version, return it +word32 BER_Decoder::GetVersion() +{ + if (source_.GetError().What()) return 0; + + byte b = source_.next(); + if (b != INTEGER) { + source_.SetError(INTEGER_E); + return 0; + } + + b = source_.next(); + if (b != 0x01) { + source_.SetError(VERSION_E); + return 0; + } + + return source_.next(); +} + + +// Read ExplicitVersion, return it or 0 if not there (not an error) +word32 BER_Decoder::GetExplicitVersion() +{ + if (source_.GetError().What()) return 0; + + byte b = source_.next(); + + if (b == (CONTEXT_SPECIFIC | CONSTRUCTED)) { // not an error if not here + source_.next(); + return GetVersion(); + } + else + source_.prev(); // put back + + return 0; +} + + +// Decode a BER encoded RSA Private Key +void RSA_Private_Decoder::Decode(RSA_PrivateKey& key) +{ + ReadHeader(); + if (source_.GetError().What()) return; + // public + key.SetModulus(GetInteger(Integer().Ref())); + key.SetPublicExponent(GetInteger(Integer().Ref())); + + // private + key.SetPrivateExponent(GetInteger(Integer().Ref())); + key.SetPrime1(GetInteger(Integer().Ref())); + key.SetPrime2(GetInteger(Integer().Ref())); + key.SetModPrime1PrivateExponent(GetInteger(Integer().Ref())); + key.SetModPrime2PrivateExponent(GetInteger(Integer().Ref())); + key.SetMultiplicativeInverseOfPrime2ModPrime1(GetInteger(Integer().Ref())); +} + + +void RSA_Private_Decoder::ReadHeader() +{ + GetSequence(); + GetVersion(); +} + + +// Decode a BER encoded DSA Private Key +void DSA_Private_Decoder::Decode(DSA_PrivateKey& key) +{ + ReadHeader(); + if (source_.GetError().What()) return; + // group parameters + key.SetModulus(GetInteger(Integer().Ref())); + key.SetSubGroupOrder(GetInteger(Integer().Ref())); + key.SetSubGroupGenerator(GetInteger(Integer().Ref())); + + // key + key.SetPublicPart(GetInteger(Integer().Ref())); + key.SetPrivatePart(GetInteger(Integer().Ref())); +} + + +void DSA_Private_Decoder::ReadHeader() +{ + GetSequence(); + GetVersion(); +} + + +// Decode a BER encoded RSA Public Key +void RSA_Public_Decoder::Decode(RSA_PublicKey& key) +{ + ReadHeader(); + if (source_.GetError().What()) return; + + ReadHeaderOpenSSL(); // may or may not be + if (source_.GetError().What()) return; + + // public key + key.SetModulus(GetInteger(Integer().Ref())); + key.SetPublicExponent(GetInteger(Integer().Ref())); +} + + +// Read OpenSSL format public header +void RSA_Public_Decoder::ReadHeaderOpenSSL() +{ + byte b = source_.next(); // peek + source_.prev(); + + if (b != INTEGER) { // have OpenSSL public format + GetSequence(); + b = source_.next(); + if (b != OBJECT_IDENTIFIER) { + source_.SetError(OBJECT_ID_E); + return; + } + + word32 len = GetLength(source_); + source_.advance(len); + + b = source_.next(); + if (b == TAG_NULL) { // could have NULL tag and 0 terminator, may not + b = source_.next(); + if (b != 0) { + source_.SetError(EXPECT_0_E); + return; + } + } + else + source_.prev(); // put back + + b = source_.next(); + if (b != BIT_STRING) { + source_.SetError(BIT_STR_E); + return; + } + + len = GetLength(source_); + b = source_.next(); + if (b != 0) // could have 0 + source_.prev(); // put back + + GetSequence(); + } +} + + +void RSA_Public_Decoder::ReadHeader() +{ + GetSequence(); +} + + +// Decode a BER encoded DSA Public Key +void DSA_Public_Decoder::Decode(DSA_PublicKey& key) +{ + ReadHeader(); + if (source_.GetError().What()) return; + + // group parameters + key.SetModulus(GetInteger(Integer().Ref())); + key.SetSubGroupOrder(GetInteger(Integer().Ref())); + key.SetSubGroupGenerator(GetInteger(Integer().Ref())); + + // key + key.SetPublicPart(GetInteger(Integer().Ref())); +} + + +void DSA_Public_Decoder::ReadHeader() +{ + GetSequence(); +} + + +void DH_Decoder::ReadHeader() +{ + GetSequence(); +} + + +// Decode a BER encoded Diffie-Hellman Key +void DH_Decoder::Decode(DH& key) +{ + ReadHeader(); + if (source_.GetError().What()) return; + + // group parms + key.SetP(GetInteger(Integer().Ref())); + key.SetG(GetInteger(Integer().Ref())); +} + + +CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers, + bool noVerify, CertType ct) + : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), subCnPos_(-1), + subCnLen_(0), issCnPos_(-1), issCnLen_(0), signature_(0), + verify_(!noVerify) +{ + issuer_[0] = 0; + subject_[0] = 0; + + if (decode) + Decode(signers, ct); + +} + + +CertDecoder::~CertDecoder() +{ + tcArrayDelete(signature_); +} + + +// process certificate header, set signature offset +void CertDecoder::ReadHeader() +{ + if (source_.GetError().What()) return; + + GetSequence(); // total + certBegin_ = source_.get_index(); + + sigIndex_ = GetSequence(); // this cert + sigIndex_ += source_.get_index(); + + GetExplicitVersion(); // version + GetInteger(Integer().Ref()); // serial number +} + + +// Decode a x509v3 Certificate +void CertDecoder::Decode(SignerList* signers, CertType ct) +{ + if (source_.GetError().What()) return; + DecodeToKey(); + if (source_.GetError().What()) return; + + if (source_.get_index() != sigIndex_) + source_.set_index(sigIndex_); + + word32 confirmOID = GetAlgoId(); + GetSignature(); + if (source_.GetError().What()) return; + + if ( confirmOID != signatureOID_ ) { + source_.SetError(SIG_OID_E); + return; + } + + if (ct != CA && verify_ && !ValidateSignature(signers)) + source_.SetError(SIG_OTHER_E); +} + + +void CertDecoder::DecodeToKey() +{ + ReadHeader(); + signatureOID_ = GetAlgoId(); + GetName(ISSUER); + GetValidity(); + GetName(SUBJECT); + GetKey(); +} + + +// Read public key +void CertDecoder::GetKey() +{ + if (source_.GetError().What()) return; + + GetSequence(); + keyOID_ = GetAlgoId(); + + if (keyOID_ == RSAk) { + byte b = source_.next(); + if (b != BIT_STRING) { + source_.SetError(BIT_STR_E); + return; + } + b = source_.next(); // length, future + b = source_.next(); + while(b != 0) + b = source_.next(); + } + else if (keyOID_ == DSAk) + ; // do nothing + else { + source_.SetError(UNKNOWN_OID_E); + return; + } + + StoreKey(); + if (keyOID_ == DSAk) + AddDSA(); +} + + +// Save public key +void CertDecoder::StoreKey() +{ + if (source_.GetError().What()) return; + + word32 read = source_.get_index(); + word32 length = GetSequence(); + + read = source_.get_index() - read; + length += read; + + if (source_.GetError().What()) return; + while (read--) source_.prev(); + + if (source_.IsLeft(length) == false) return; + key_.SetSize(length); + key_.SetKey(source_.get_current()); + source_.advance(length); +} + + +// DSA has public key after group +void CertDecoder::AddDSA() +{ + if (source_.GetError().What()) return; + + byte b = source_.next(); + if (b != BIT_STRING) { + source_.SetError(BIT_STR_E); + return; + } + b = source_.next(); // length, future + b = source_.next(); + while(b != 0) + b = source_.next(); + + word32 idx = source_.get_index(); + b = source_.next(); + if (b != INTEGER) { + source_.SetError(INTEGER_E); + return; + } + + word32 length = GetLength(source_); + length += source_.get_index() - idx; + + if (source_.IsLeft(length) == false) return; + + key_.AddToEnd(source_.get_buffer() + idx, length); +} + + +// process algo OID by summing, return it +word32 CertDecoder::GetAlgoId() +{ + if (source_.GetError().What()) return 0; + word32 length = GetSequence(); + + if (source_.GetError().What()) return 0; + + byte b = source_.next(); + if (b != OBJECT_IDENTIFIER) { + source_.SetError(OBJECT_ID_E); + return 0; + } + + length = GetLength(source_); + if (source_.IsLeft(length) == false) return 0; + + word32 oid = 0; + while(length--) + oid += source_.next(); // just sum it up for now + + // could have NULL tag and 0 terminator, but may not + b = source_.next(); + if (b == TAG_NULL) { + b = source_.next(); + if (b != 0) { + source_.SetError(EXPECT_0_E); + return 0; + } + } + else + // go back, didn't have it + b = source_.prev(); + + return oid; +} + + +// read cert signature, store in signature_ +word32 CertDecoder::GetSignature() +{ + if (source_.GetError().What()) return 0; + byte b = source_.next(); + + if (b != BIT_STRING) { + source_.SetError(BIT_STR_E); + return 0; + } + + sigLength_ = GetLength(source_); + if (sigLength_ <= 1 || source_.IsLeft(sigLength_) == false) { + source_.SetError(CONTENT_E); + return 0; + } + + b = source_.next(); + if (b != 0) { + source_.SetError(EXPECT_0_E); + return 0; + } + sigLength_--; + + signature_ = NEW_TC byte[sigLength_]; + memcpy(signature_, source_.get_current(), sigLength_); + source_.advance(sigLength_); + + return sigLength_; +} + + +// read cert digest, store in signature_ +word32 CertDecoder::GetDigest() +{ + if (source_.GetError().What()) return 0; + byte b = source_.next(); + + if (b != OCTET_STRING) { + source_.SetError(OCTET_STR_E); + return 0; + } + + sigLength_ = GetLength(source_); + + signature_ = NEW_TC byte[sigLength_]; + memcpy(signature_, source_.get_current(), sigLength_); + source_.advance(sigLength_); + + return sigLength_; +} + + +// memory length checked add tag to buffer +char* CertDecoder::AddTag(char* ptr, const char* buf_end, const char* tag_name, + word32 tag_name_length, word32 tag_value_length) +{ + if (ptr + tag_name_length + tag_value_length > buf_end) { + source_.SetError(CONTENT_E); + return 0; + } + + memcpy(ptr, tag_name, tag_name_length); + ptr += tag_name_length; + + memcpy(ptr, source_.get_current(), tag_value_length); + ptr += tag_value_length; + + return ptr; +} + + +// process NAME, either issuer or subject +void CertDecoder::GetName(NameType nt) +{ + if (source_.GetError().What()) return; + + SHA sha; + word32 length = GetSequence(); // length of all distinguished names + + if (length >= ASN_NAME_MAX) + return; + if (source_.IsLeft(length) == false) return; + length += source_.get_index(); + + char* ptr; + char* buf_end; + + if (nt == ISSUER) { + ptr = issuer_; + buf_end = ptr + sizeof(issuer_) - 1; // 1 byte for trailing 0 + } + else { + ptr = subject_; + buf_end = ptr + sizeof(subject_) - 1; // 1 byte for trailing 0 + } + + while (source_.get_index() < length) { + GetSet(); + if (source_.GetError().What() == SET_E) { + source_.SetError(NO_ERROR_E); // extensions may only have sequence + source_.prev(); + } + GetSequence(); + + byte b = source_.next(); + if (b != OBJECT_IDENTIFIER) { + source_.SetError(OBJECT_ID_E); + return; + } + + word32 oidSz = GetLength(source_); + if (source_.IsLeft(oidSz) == false) return; + + byte joint[2]; + if (source_.IsLeft(sizeof(joint)) == false) return; + memcpy(joint, source_.get_current(), sizeof(joint)); + + // v1 name types + if (joint[0] == 0x55 && joint[1] == 0x04) { + source_.advance(2); + byte id = source_.next(); + b = source_.next(); // strType + word32 strLen = GetLength(source_); + + if (source_.IsLeft(strLen) == false) return; + + switch (id) { + case COMMON_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen))) + return; + if (nt == ISSUER) { + issCnPos_ = (int)(ptr - strLen - issuer_); + issCnLen_ = (int)strLen; + } else { + subCnPos_ = (int)(ptr - strLen - subject_); + subCnLen_ = (int)strLen; + } + break; + case SUR_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/SN=", 4, strLen))) + return; + break; + case COUNTRY_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/C=", 3, strLen))) + return; + break; + case LOCALITY_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/L=", 3, strLen))) + return; + break; + case STATE_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/ST=", 4, strLen))) + return; + break; + case ORG_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/O=", 3, strLen))) + return; + break; + case ORGUNIT_NAME: + if (!(ptr = AddTag(ptr, buf_end, "/OU=", 4, strLen))) + return; + break; + } + + sha.Update(source_.get_current(), strLen); + source_.advance(strLen); + } + else { + bool email = false; + if (joint[0] == 0x2a && joint[1] == 0x86) // email id hdr + email = true; + + source_.advance(oidSz + 1); + word32 length = GetLength(source_); + if (source_.IsLeft(length) == false) return; + + if (email) { + if (!(ptr = AddTag(ptr, buf_end, "/emailAddress=", 14, length))) + return; + } + + source_.advance(length); + } + } + + *ptr = 0; + + if (nt == ISSUER) + sha.Final(issuerHash_); + else + sha.Final(subjectHash_); +} + + +// process a Date, either BEFORE or AFTER +void CertDecoder::GetDate(DateType dt) +{ + if (source_.GetError().What()) return; + + byte b = source_.next(); + if (b != UTC_TIME && b != GENERALIZED_TIME) { + source_.SetError(TIME_E); + return; + } + + word32 length = GetLength(source_); + if (source_.IsLeft(length) == false) return; + + byte date[MAX_DATE_SZ]; + if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) { + source_.SetError(DATE_SZ_E); + return; + } + + memcpy(date, source_.get_current(), length); + source_.advance(length); + + if (!ValidateDate(date, b, dt) && verify_) { + if (dt == BEFORE) + source_.SetError(BEFORE_DATE_E); + else + source_.SetError(AFTER_DATE_E); + } + + // save for later use + if (dt == BEFORE) { + memcpy(beforeDate_, date, length); + beforeDate_[length] = 0; + beforeDateType_= b; + } + else { // after + memcpy(afterDate_, date, length); + afterDate_[length] = 0; + afterDateType_= b; + } +} + + +void CertDecoder::GetValidity() +{ + if (source_.GetError().What()) return; + + GetSequence(); + GetDate(BEFORE); + GetDate(AFTER); +} + + +bool CertDecoder::ValidateSelfSignature() +{ + Source pub(key_.GetKey(), key_.size()); + return ConfirmSignature(pub); +} + + +// extract compare signature hash from plain and place into digest +void CertDecoder::GetCompareHash(const byte* plain, word32 sz, byte* digest, + word32 digSz) +{ + if (source_.GetError().What()) return; + + Source s(plain, sz); + CertDecoder dec(s, false); + + dec.GetSequence(); + dec.GetAlgoId(); + dec.GetDigest(); + + if (dec.sigLength_ > digSz) { + source_.SetError(SIG_LEN_E); + return; + } + + memcpy(digest, dec.signature_, dec.sigLength_); +} + + +// validate signature signed by someone else +bool CertDecoder::ValidateSignature(SignerList* signers) +{ + if (!signers) + return false; + + SignerList::iterator first = signers->begin(); + SignerList::iterator last = signers->end(); + + while (first != last) { + if ( memcmp(issuerHash_, (*first)->GetHash(), SHA::DIGEST_SIZE) == 0) { + + const PublicKey& iKey = (*first)->GetPublicKey(); + Source pub(iKey.GetKey(), iKey.size()); + return ConfirmSignature(pub); + } + ++first; + } + return false; +} + + +// confirm certificate signature +bool CertDecoder::ConfirmSignature(Source& pub) +{ + HashType ht; + mySTL::auto_ptr hasher; + + if (signatureOID_ == MD5wRSA) { + hasher.reset(NEW_TC MD5); + ht = MD5h; + } + else if (signatureOID_ == MD2wRSA) { + hasher.reset(NEW_TC MD2); + ht = MD2h; + } + else if (signatureOID_ == SHAwRSA || signatureOID_ == SHAwDSA) { + hasher.reset(NEW_TC SHA); + ht = SHAh; + } + else if (signatureOID_ == SHA256wRSA || signatureOID_ == SHA256wDSA) { + hasher.reset(NEW_TC SHA256); + ht = SHA256h; + } +#ifdef WORD64_AVAILABLE + else if (signatureOID_ == SHA384wRSA) { + hasher.reset(NEW_TC SHA384); + ht = SHA384h; + } + else if (signatureOID_ == SHA512wRSA) { + hasher.reset(NEW_TC SHA512); + ht = SHA512h; + } +#endif + else { + source_.SetError(UNKOWN_SIG_E); + return false; + } + + byte digest[MAX_SHA2_DIGEST_SIZE]; // largest size + + hasher->Update(source_.get_buffer() + certBegin_, sigIndex_ - certBegin_); + hasher->Final(digest); + + if (keyOID_ == RSAk) { + // put in ASN.1 signature format + Source build; + Signature_Encoder(digest, hasher->getDigestSize(), ht, build); + + RSA_PublicKey pubKey(pub); + RSAES_Encryptor enc(pubKey); + + if (pubKey.FixedCiphertextLength() != sigLength_) { + source_.SetError(SIG_LEN_E); + return false; + } + + return enc.SSL_Verify(build.get_buffer(), build.size(), signature_); + } + else { // DSA + // extract r and s from sequence + byte seqDecoded[DSA_SIG_SZ]; + memset(seqDecoded, 0, sizeof(seqDecoded)); + DecodeDSA_Signature(seqDecoded, signature_, sigLength_); + + DSA_PublicKey pubKey(pub); + DSA_Verifier ver(pubKey); + + return ver.Verify(digest, seqDecoded); + } +} + + +Signature_Encoder::Signature_Encoder(const byte* dig, word32 digSz, + HashType digOID, Source& source) +{ + // build bottom up + + // Digest + byte digArray[MAX_DIGEST_SZ]; + word32 digestSz = SetDigest(dig, digSz, digArray); + + // AlgoID + byte algoArray[MAX_ALGO_SZ]; + word32 algoSz = SetAlgoID(digOID, algoArray); + + // Sequence + byte seqArray[MAX_SEQ_SZ]; + word32 seqSz = SetSequence(digestSz + algoSz, seqArray); + + source.grow(seqSz + algoSz + digestSz); // make sure enough room + source.add(seqArray, seqSz); + source.add(algoArray, algoSz); + source.add(digArray, digestSz); +} + + + +word32 Signature_Encoder::SetDigest(const byte* d, word32 dSz, byte* output) +{ + output[0] = OCTET_STRING; + output[1] = dSz; + memcpy(&output[2], d, dSz); + + return dSz + 2; +} + + + +word32 DER_Encoder::SetAlgoID(HashType aOID, byte* output) +{ + // adding TAG_NULL and 0 to end + static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00 }; + static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x02, 0x05, 0x05, 0x00 }; + static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x02, 0x02, 0x05, 0x00}; + static const byte sha256AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x05, 0x00 }; + static const byte sha384AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x02, 0x05, 0x00 }; + static const byte sha512AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x03, 0x05, 0x00 }; + int algoSz = 0; + const byte* algoName = 0; + + switch (aOID) { + case SHAh: + algoSz = sizeof(shaAlgoID); + algoName = shaAlgoID; + break; + + case SHA256h: + algoSz = sizeof(sha256AlgoID); + algoName = sha256AlgoID; + break; + + case SHA384h: + algoSz = sizeof(sha384AlgoID); + algoName = sha384AlgoID; + break; + + case SHA512h: + algoSz = sizeof(sha512AlgoID); + algoName = sha512AlgoID; + break; + + case MD2h: + algoSz = sizeof(md2AlgoID); + algoName = md2AlgoID; + break; + + case MD5h: + algoSz = sizeof(md5AlgoID); + algoName = md5AlgoID; + break; + + default: + error_.SetError(UNKOWN_HASH_E); + return 0; + } + + + byte ID_Length[MAX_LENGTH_SZ]; + word32 idSz = SetLength(algoSz - 2, ID_Length); // don't include TAG_NULL/0 + + byte seqArray[MAX_SEQ_SZ + 1]; // add object_id to end + word32 seqSz = SetSequence(idSz + algoSz + 1, seqArray); + seqArray[seqSz++] = OBJECT_IDENTIFIER; + + memcpy(output, seqArray, seqSz); + memcpy(output + seqSz, ID_Length, idSz); + memcpy(output + seqSz + idSz, algoName, algoSz); + + return seqSz + idSz + algoSz; +} + + +word32 SetSequence(word32 len, byte* output) +{ + + output[0] = SEQUENCE | CONSTRUCTED; + return SetLength(len, output + 1) + 1; +} + + +word32 EncodeDSA_Signature(const byte* signature, byte* output) +{ + Integer r(signature, 20); + Integer s(signature + 20, 20); + + return EncodeDSA_Signature(r, s, output); +} + + +word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output) +{ + word32 rSz = r.ByteCount(); + word32 sSz = s.ByteCount(); + + byte rLen[MAX_LENGTH_SZ + 1]; + byte sLen[MAX_LENGTH_SZ + 1]; + + rLen[0] = INTEGER; + sLen[0] = INTEGER; + + word32 rLenSz = SetLength(rSz, &rLen[1]) + 1; + word32 sLenSz = SetLength(sSz, &sLen[1]) + 1; + + byte seqArray[MAX_SEQ_SZ]; + + word32 seqSz = SetSequence(rLenSz + rSz + sLenSz + sSz, seqArray); + + // seq + memcpy(output, seqArray, seqSz); + // r + memcpy(output + seqSz, rLen, rLenSz); + r.Encode(output + seqSz + rLenSz, rSz); + // s + memcpy(output + seqSz + rLenSz + rSz, sLen, sLenSz); + s.Encode(output + seqSz + rLenSz + rSz + sLenSz, sSz); + + return seqSz + rLenSz + rSz + sLenSz + sSz; +} + + +// put sequence encoded dsa signature into decoded in 2 20 byte integers +word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz) +{ + Source source(encoded, sz); + + if (source.next() != (SEQUENCE | CONSTRUCTED)) { + source.SetError(SEQUENCE_E); + return 0; + } + + GetLength(source); // total + + // r + if (source.next() != INTEGER) { + source.SetError(INTEGER_E); + return 0; + } + word32 rLen = GetLength(source); + if (rLen != 20) { + while (rLen > 20 && source.remaining() > 0) { // zero's at front, eat + source.next(); + --rLen; + } + if (rLen < 20) { // add zero's to front so 20 bytes + word32 tmpLen = rLen; + while (tmpLen < 20) { + decoded[0] = 0; + decoded++; + tmpLen++; + } + } + } + memcpy(decoded, source.get_buffer() + source.get_index(), rLen); + source.advance(rLen); + + // s + if (source.next() != INTEGER) { + source.SetError(INTEGER_E); + return 0; + } + word32 sLen = GetLength(source); + if (sLen != 20) { + while (sLen > 20 && source.remaining() > 0) { + source.next(); // zero's at front, eat + --sLen; + } + if (sLen < 20) { // add zero's to front so 20 bytes + word32 tmpLen = sLen; + while (tmpLen < 20) { + decoded[rLen] = 0; + decoded++; + tmpLen++; + } + } + } + memcpy(decoded + rLen, source.get_buffer() + source.get_index(), sLen); + source.advance(sLen); + + return 40; +} + + +/* +// Get Cert in PEM format from BEGIN to END +int GetCert(Source& source) +{ + char header[] = "-----BEGIN CERTIFICATE-----"; + char footer[] = "-----END CERTIFICATE-----"; + + char* begin = strstr((char*)source.get_buffer(), header); + char* end = strstr((char*)source.get_buffer(), footer); + + if (!begin || !end || begin >= end) return -1; + + end += strlen(footer); + if (*end == '\r') end++; + + Source tmp((byte*)begin, end - begin + 1); + source.Swap(tmp); + + return 0; +} + + + +// Decode a BER encoded PKCS12 structure +void PKCS12_Decoder::Decode() +{ + ReadHeader(); + if (source_.GetError().What()) return; + + // Get AuthSafe + + GetSequence(); + + // get object id + byte obj_id = source_.next(); + if (obj_id != OBJECT_IDENTIFIER) { + source_.SetError(OBJECT_ID_E); + return; + } + + word32 length = GetLength(source_); + + word32 algo_sum = 0; + while (length--) + algo_sum += source_.next(); + + + + + + + // Get MacData optional + // mac digestInfo like certdecoder::getdigest? + // macsalt octet string + // iter integer + +} + + +void PKCS12_Decoder::ReadHeader() +{ + // Gets Version + GetSequence(); + GetVersion(); +} + + +// Get Cert in PEM format from pkcs12 file +int GetPKCS_Cert(const char* password, Source& source) +{ + PKCS12_Decoder pkcs12(source); + pkcs12.Decode(); + + return 0; +} +*/ + + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/coding.cpp b/mysql/extra/yassl/taocrypt/src/coding.cpp new file mode 100644 index 0000000..bc4727c --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/coding.cpp @@ -0,0 +1,266 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* coding.cpp implements hex and base64 encoding/decoing +*/ + +#include "runtime.hpp" +#include "coding.hpp" +#include "file.hpp" + + +namespace TaoCrypt { + + +namespace { // locals + +const byte bad = 0xFF; // invalid encoding + +const byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' + }; + +const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + bad, bad, bad, bad, bad, bad, bad, + 10, 11, 12, 13, 14, 15 + }; // A starts at 0x41 not 0x3A + + +const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+', '/' + }; + +const byte base64Decode[] = { 62, bad, bad, bad, 63, // + starts at 0x2B + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + bad, bad, bad, bad, bad, bad, bad, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, + bad, bad, bad, bad, bad, bad, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51 + }; + +const byte pad = '='; +const int pemLineSz = 64; + +} // local namespace + + +// Hex Encode +void HexEncoder::Encode() +{ + word32 bytes = plain_.size(); + encoded_.New(bytes * 2); + + word32 i = 0; + + while (bytes--) { + byte p = plain_.next(); + + byte b = p >> 4; + byte b2 = p & 0xF; + + encoded_[i++] = hexEncode[b]; + encoded_[i++] = hexEncode[b2]; + } + + plain_.reset(encoded_); +} + + +// Hex Decode +void HexDecoder::Decode() +{ + word32 bytes = coded_.size(); + decoded_.New(bytes / 2); + + word32 i(0); + + while (bytes) { + byte b = coded_.next() - 0x30; // 0 starts at 0x30 + byte b2 = coded_.next() - 0x30; + + // sanity checks + if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) { + coded_.SetError(PEM_E); + return; + } + if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) { + coded_.SetError(PEM_E); + return; + } + + b = hexDecode[b]; + b2 = hexDecode[b2]; + + decoded_[i++] = (b << 4) | b2; + bytes -= 2; + } + + coded_.reset(decoded_); +} + + +// Base 64 Encode +void Base64Encoder::Encode() +{ + word32 bytes = plain_.size(); + word32 outSz = (bytes + 3 - 1) / 3 * 4; + + outSz += (outSz + pemLineSz - 1) / pemLineSz; // new lines + encoded_.New(outSz); + + word32 i = 0; + word32 j = 0; + + while (bytes > 2) { + byte b1 = plain_.next(); + byte b2 = plain_.next(); + byte b3 = plain_.next(); + + // encoded idx + byte e1 = b1 >> 2; + byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4); + byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6); + byte e4 = b3 & 0x3F; + + // store + encoded_[i++] = base64Encode[e1]; + encoded_[i++] = base64Encode[e2]; + encoded_[i++] = base64Encode[e3]; + encoded_[i++] = base64Encode[e4]; + + bytes -= 3; + + if ((++j % 16) == 0 && bytes) + encoded_[i++] = '\n'; + } + + // last integral + if (bytes) { + bool twoBytes = (bytes == 2); + + byte b1 = plain_.next(); + byte b2 = (twoBytes) ? plain_.next() : 0; + + byte e1 = b1 >> 2; + byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4); + byte e3 = (b2 & 0xF) << 2; + + encoded_[i++] = base64Encode[e1]; + encoded_[i++] = base64Encode[e2]; + encoded_[i++] = (twoBytes) ? base64Encode[e3] : pad; + encoded_[i++] = pad; + } + + encoded_[i++] = '\n'; + + if (i == outSz) + plain_.reset(encoded_); +} + + +// Base 64 Decode +void Base64Decoder::Decode() +{ + word32 bytes = coded_.size(); + word32 plainSz = bytes - ((bytes + (pemLineSz - 1)) / pemLineSz); + const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1; + plainSz = ((plainSz * 3) / 4) + 3; + decoded_.New(plainSz); + + word32 i = 0; + word32 j = 0; + + while (bytes > 3) { + byte e1 = coded_.next(); + byte e2 = coded_.next(); + byte e3 = coded_.next(); + byte e4 = coded_.next(); + + if (e1 == 0) // end file 0's + break; + + bool pad3 = false; + bool pad4 = false; + if (e3 == pad) + pad3 = true; + if (e4 == pad) + pad4 = true; + + if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) { + coded_.SetError(PEM_E); + return; + } + + if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) { + coded_.SetError(PEM_E); + return; + } + + e1 = base64Decode[e1 - 0x2B]; + e2 = base64Decode[e2 - 0x2B]; + e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B]; + e4 = (e4 == pad) ? 0 : base64Decode[e4 - 0x2B]; + + byte b1 = (e1 << 2) | (e2 >> 4); + byte b2 = ((e2 & 0xF) << 4) | (e3 >> 2); + byte b3 = ((e3 & 0x3) << 6) | e4; + + decoded_[i++] = b1; + if (!pad3) + decoded_[i++] = b2; + if (!pad4) + decoded_[i++] = b3; + else + break; + + bytes -= 4; + if ((++j % 16) == 0) { + byte endLine = coded_.next(); + bytes--; + while (endLine == ' ') { // remove possible whitespace + endLine = coded_.next(); + bytes--; + } + if (endLine == '\r') { + endLine = coded_.next(); + bytes--; + } + if (endLine != '\n') { + coded_.SetError(PEM_E); + return; + } + } + } + + if (i != decoded_.size()) + decoded_.resize(i); + coded_.reset(decoded_); +} + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/des.cpp b/mysql/extra/yassl/taocrypt/src/des.cpp new file mode 100644 index 0000000..53777f0 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/des.cpp @@ -0,0 +1,778 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* C++ part based on Wei Dai's des.cpp from CryptoPP */ +/* x86 asm is original */ + + +#if defined(TAOCRYPT_KERNEL_MODE) + #define DO_TAOCRYPT_KERNEL_MODE +#endif // only some modules now support this + + +#include "runtime.hpp" +#include "des.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + + +namespace TaoCrypt { + + +/* permuted choice table (key) */ +static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + +const word32 Spbox[8][64] = { +{ +0x01010400,0x00000000,0x00010000,0x01010404, +0x01010004,0x00010404,0x00000004,0x00010000, +0x00000400,0x01010400,0x01010404,0x00000400, +0x01000404,0x01010004,0x01000000,0x00000004, +0x00000404,0x01000400,0x01000400,0x00010400, +0x00010400,0x01010000,0x01010000,0x01000404, +0x00010004,0x01000004,0x01000004,0x00010004, +0x00000000,0x00000404,0x00010404,0x01000000, +0x00010000,0x01010404,0x00000004,0x01010000, +0x01010400,0x01000000,0x01000000,0x00000400, +0x01010004,0x00010000,0x00010400,0x01000004, +0x00000400,0x00000004,0x01000404,0x00010404, +0x01010404,0x00010004,0x01010000,0x01000404, +0x01000004,0x00000404,0x00010404,0x01010400, +0x00000404,0x01000400,0x01000400,0x00000000, +0x00010004,0x00010400,0x00000000,0x01010004}, +{ +0x80108020,0x80008000,0x00008000,0x00108020, +0x00100000,0x00000020,0x80100020,0x80008020, +0x80000020,0x80108020,0x80108000,0x80000000, +0x80008000,0x00100000,0x00000020,0x80100020, +0x00108000,0x00100020,0x80008020,0x00000000, +0x80000000,0x00008000,0x00108020,0x80100000, +0x00100020,0x80000020,0x00000000,0x00108000, +0x00008020,0x80108000,0x80100000,0x00008020, +0x00000000,0x00108020,0x80100020,0x00100000, +0x80008020,0x80100000,0x80108000,0x00008000, +0x80100000,0x80008000,0x00000020,0x80108020, +0x00108020,0x00000020,0x00008000,0x80000000, +0x00008020,0x80108000,0x00100000,0x80000020, +0x00100020,0x80008020,0x80000020,0x00100020, +0x00108000,0x00000000,0x80008000,0x00008020, +0x80000000,0x80100020,0x80108020,0x00108000}, +{ +0x00000208,0x08020200,0x00000000,0x08020008, +0x08000200,0x00000000,0x00020208,0x08000200, +0x00020008,0x08000008,0x08000008,0x00020000, +0x08020208,0x00020008,0x08020000,0x00000208, +0x08000000,0x00000008,0x08020200,0x00000200, +0x00020200,0x08020000,0x08020008,0x00020208, +0x08000208,0x00020200,0x00020000,0x08000208, +0x00000008,0x08020208,0x00000200,0x08000000, +0x08020200,0x08000000,0x00020008,0x00000208, +0x00020000,0x08020200,0x08000200,0x00000000, +0x00000200,0x00020008,0x08020208,0x08000200, +0x08000008,0x00000200,0x00000000,0x08020008, +0x08000208,0x00020000,0x08000000,0x08020208, +0x00000008,0x00020208,0x00020200,0x08000008, +0x08020000,0x08000208,0x00000208,0x08020000, +0x00020208,0x00000008,0x08020008,0x00020200}, +{ +0x00802001,0x00002081,0x00002081,0x00000080, +0x00802080,0x00800081,0x00800001,0x00002001, +0x00000000,0x00802000,0x00802000,0x00802081, +0x00000081,0x00000000,0x00800080,0x00800001, +0x00000001,0x00002000,0x00800000,0x00802001, +0x00000080,0x00800000,0x00002001,0x00002080, +0x00800081,0x00000001,0x00002080,0x00800080, +0x00002000,0x00802080,0x00802081,0x00000081, +0x00800080,0x00800001,0x00802000,0x00802081, +0x00000081,0x00000000,0x00000000,0x00802000, +0x00002080,0x00800080,0x00800081,0x00000001, +0x00802001,0x00002081,0x00002081,0x00000080, +0x00802081,0x00000081,0x00000001,0x00002000, +0x00800001,0x00002001,0x00802080,0x00800081, +0x00002001,0x00002080,0x00800000,0x00802001, +0x00000080,0x00800000,0x00002000,0x00802080}, +{ +0x00000100,0x02080100,0x02080000,0x42000100, +0x00080000,0x00000100,0x40000000,0x02080000, +0x40080100,0x00080000,0x02000100,0x40080100, +0x42000100,0x42080000,0x00080100,0x40000000, +0x02000000,0x40080000,0x40080000,0x00000000, +0x40000100,0x42080100,0x42080100,0x02000100, +0x42080000,0x40000100,0x00000000,0x42000000, +0x02080100,0x02000000,0x42000000,0x00080100, +0x00080000,0x42000100,0x00000100,0x02000000, +0x40000000,0x02080000,0x42000100,0x40080100, +0x02000100,0x40000000,0x42080000,0x02080100, +0x40080100,0x00000100,0x02000000,0x42080000, +0x42080100,0x00080100,0x42000000,0x42080100, +0x02080000,0x00000000,0x40080000,0x42000000, +0x00080100,0x02000100,0x40000100,0x00080000, +0x00000000,0x40080000,0x02080100,0x40000100}, +{ +0x20000010,0x20400000,0x00004000,0x20404010, +0x20400000,0x00000010,0x20404010,0x00400000, +0x20004000,0x00404010,0x00400000,0x20000010, +0x00400010,0x20004000,0x20000000,0x00004010, +0x00000000,0x00400010,0x20004010,0x00004000, +0x00404000,0x20004010,0x00000010,0x20400010, +0x20400010,0x00000000,0x00404010,0x20404000, +0x00004010,0x00404000,0x20404000,0x20000000, +0x20004000,0x00000010,0x20400010,0x00404000, +0x20404010,0x00400000,0x00004010,0x20000010, +0x00400000,0x20004000,0x20000000,0x00004010, +0x20000010,0x20404010,0x00404000,0x20400000, +0x00404010,0x20404000,0x00000000,0x20400010, +0x00000010,0x00004000,0x20400000,0x00404010, +0x00004000,0x00400010,0x20004010,0x00000000, +0x20404000,0x20000000,0x00400010,0x20004010}, +{ +0x00200000,0x04200002,0x04000802,0x00000000, +0x00000800,0x04000802,0x00200802,0x04200800, +0x04200802,0x00200000,0x00000000,0x04000002, +0x00000002,0x04000000,0x04200002,0x00000802, +0x04000800,0x00200802,0x00200002,0x04000800, +0x04000002,0x04200000,0x04200800,0x00200002, +0x04200000,0x00000800,0x00000802,0x04200802, +0x00200800,0x00000002,0x04000000,0x00200800, +0x04000000,0x00200800,0x00200000,0x04000802, +0x04000802,0x04200002,0x04200002,0x00000002, +0x00200002,0x04000000,0x04000800,0x00200000, +0x04200800,0x00000802,0x00200802,0x04200800, +0x00000802,0x04000002,0x04200802,0x04200000, +0x00200800,0x00000000,0x00000002,0x04200802, +0x00000000,0x00200802,0x04200000,0x00000800, +0x04000002,0x04000800,0x00000800,0x00200002}, +{ +0x10001040,0x00001000,0x00040000,0x10041040, +0x10000000,0x10001040,0x00000040,0x10000000, +0x00040040,0x10040000,0x10041040,0x00041000, +0x10041000,0x00041040,0x00001000,0x00000040, +0x10040000,0x10000040,0x10001000,0x00001040, +0x00041000,0x00040040,0x10040040,0x10041000, +0x00001040,0x00000000,0x00000000,0x10040040, +0x10000040,0x10001000,0x00041040,0x00040000, +0x00041040,0x00040000,0x10041000,0x00001000, +0x00000040,0x10040040,0x00001000,0x00041040, +0x10001000,0x00000040,0x10000040,0x10040000, +0x10040040,0x10000000,0x00040000,0x10001040, +0x00000000,0x10041040,0x00040040,0x10000040, +0x10040000,0x10001000,0x10001040,0x00000000, +0x10041040,0x00041000,0x00041000,0x00001040, +0x00001040,0x00040040,0x10000000,0x10041000} +}; + + +void BasicDES::SetKey(const byte* key, word32 /*length*/, CipherDir dir) +{ + byte buffer[56+56+8]; + byte *const pc1m = buffer; /* place to modify pc1 into */ + byte *const pcr = pc1m + 56; /* place to rotate pc1 into */ + byte *const ks = pcr + 56; + int i,j,l; + int m; + + for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ + l = pc1[j] - 1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i = 0; i < 16; i++) { /* key chunk for each iteration */ + memset(ks, 0, 8); /* Clear key schedule */ + for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j = 0; j < 48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j] - 1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to odd/even interleaved form for use in F */ + k_[2*i] = ((word32)ks[0] << 24) + | ((word32)ks[2] << 16) + | ((word32)ks[4] << 8) + | ((word32)ks[6]); + k_[2*i + 1] = ((word32)ks[1] << 24) + | ((word32)ks[3] << 16) + | ((word32)ks[5] << 8) + | ((word32)ks[7]); + } + + // reverse key schedule order + if (dir == DECRYPTION) + for (i = 0; i < 16; i += 2) { + STL::swap(k_[i], k_[32 - 2 - i]); + STL::swap(k_[i+1], k_[32 - 1 - i]); + } + +} + +static inline void IPERM(word32& left, word32& right) +{ + word32 work; + + right = rotlFixed(right, 4U); + work = (left ^ right) & 0xf0f0f0f0; + left ^= work; + + right = rotrFixed(right^work, 20U); + work = (left ^ right) & 0xffff0000; + left ^= work; + + right = rotrFixed(right^work, 18U); + work = (left ^ right) & 0x33333333; + left ^= work; + + right = rotrFixed(right^work, 6U); + work = (left ^ right) & 0x00ff00ff; + left ^= work; + + right = rotlFixed(right^work, 9U); + work = (left ^ right) & 0xaaaaaaaa; + left = rotlFixed(left^work, 1U); + right ^= work; +} + +static inline void FPERM(word32& left, word32& right) +{ + word32 work; + + right = rotrFixed(right, 1U); + work = (left ^ right) & 0xaaaaaaaa; + right ^= work; + left = rotrFixed(left^work, 9U); + work = (left ^ right) & 0x00ff00ff; + right ^= work; + left = rotlFixed(left^work, 6U); + work = (left ^ right) & 0x33333333; + right ^= work; + left = rotlFixed(left^work, 18U); + work = (left ^ right) & 0xffff0000; + right ^= work; + left = rotlFixed(left^work, 20U); + work = (left ^ right) & 0xf0f0f0f0; + right ^= work; + left = rotrFixed(left^work, 4U); +} + + +void BasicDES::RawProcessBlock(word32& lIn, word32& rIn) const +{ + word32 l = lIn, r = rIn; + const word32* kptr = k_; + + for (unsigned i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + lIn = l; rIn = r; +} + + + +typedef BlockGetAndPut Block; + + +void DES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const +{ + word32 l,r; + Block::Get(in)(l)(r); + IPERM(l,r); + + RawProcessBlock(l, r); + + FPERM(l,r); + Block::Put(xOr, out)(r)(l); +} + + +void DES_EDE2::SetKey(const byte* key, word32 sz, CipherDir dir) +{ + des1_.SetKey(key, sz, dir); + des2_.SetKey(key + 8, sz, ReverseDir(dir)); +} + + +void DES_EDE2::ProcessAndXorBlock(const byte* in, const byte* xOr, + byte* out) const +{ + word32 l,r; + Block::Get(in)(l)(r); + IPERM(l,r); + + des1_.RawProcessBlock(l, r); + des2_.RawProcessBlock(r, l); + des1_.RawProcessBlock(l, r); + + FPERM(l,r); + Block::Put(xOr, out)(r)(l); +} + + +void DES_EDE3::SetKey(const byte* key, word32 sz, CipherDir dir) +{ + des1_.SetKey(key+(dir==ENCRYPTION?0:2*8), sz, dir); + des2_.SetKey(key+8, sz, ReverseDir(dir)); + des3_.SetKey(key+(dir==DECRYPTION?0:2*8), sz, dir); +} + + + +#if defined(DO_DES_ASM) + +// ia32 optimized version +void DES_EDE3::Process(byte* out, const byte* in, word32 sz) +{ + if (!isMMX) { + Mode_BASE::Process(out, in, sz); + return; + } + + word32 blocks = sz / DES_BLOCK_SIZE; + + if (mode_ == CBC) + if (dir_ == ENCRYPTION) + while (blocks--) { + r_[0] ^= *(word32*)in; + r_[1] ^= *(word32*)(in + 4); + + AsmProcess((byte*)r_, (byte*)r_, (void*)Spbox); + + memcpy(out, r_, DES_BLOCK_SIZE); + + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + else + while (blocks--) { + AsmProcess(in, out, (void*)Spbox); + + *(word32*)out ^= r_[0]; + *(word32*)(out + 4) ^= r_[1]; + + memcpy(r_, in, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + else + while (blocks--) { + AsmProcess(in, out, (void*)Spbox); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } +} + +#endif // DO_DES_ASM + + +void DES_EDE3::ProcessAndXorBlock(const byte* in, const byte* xOr, + byte* out) const +{ + word32 l,r; + Block::Get(in)(l)(r); + IPERM(l,r); + + des1_.RawProcessBlock(l, r); + des2_.RawProcessBlock(r, l); + des3_.RawProcessBlock(l, r); + + FPERM(l,r); + Block::Put(xOr, out)(r)(l); +} + + +#if defined(DO_DES_ASM) + +/* Uses IPERM algorithm from above + + left is in eax + right is in ebx + + uses ecx +*/ +#define AsmIPERM() \ + AS2( rol ebx, 4 ) \ + AS2( mov ecx, eax ) \ + AS2( xor ecx, ebx ) \ + AS2( and ecx, 0xf0f0f0f0 ) \ + AS2( xor ebx, ecx ) \ + AS2( xor eax, ecx ) \ + AS2( ror ebx, 20 ) \ + AS2( mov ecx, eax ) \ + AS2( xor ecx, ebx ) \ + AS2( and ecx, 0xffff0000 ) \ + AS2( xor ebx, ecx ) \ + AS2( xor eax, ecx ) \ + AS2( ror ebx, 18 ) \ + AS2( mov ecx, eax ) \ + AS2( xor ecx, ebx ) \ + AS2( and ecx, 0x33333333 ) \ + AS2( xor ebx, ecx ) \ + AS2( xor eax, ecx ) \ + AS2( ror ebx, 6 ) \ + AS2( mov ecx, eax ) \ + AS2( xor ecx, ebx ) \ + AS2( and ecx, 0x00ff00ff ) \ + AS2( xor ebx, ecx ) \ + AS2( xor eax, ecx ) \ + AS2( rol ebx, 9 ) \ + AS2( mov ecx, eax ) \ + AS2( xor ecx, ebx ) \ + AS2( and ecx, 0xaaaaaaaa ) \ + AS2( xor eax, ecx ) \ + AS2( rol eax, 1 ) \ + AS2( xor ebx, ecx ) + + +/* Uses FPERM algorithm from above + + left is in eax + right is in ebx + + uses ecx +*/ +#define AsmFPERM() \ + AS2( ror ebx, 1 ) \ + AS2( mov ecx, eax ) \ + AS2( xor ecx, ebx ) \ + AS2( and ecx, 0xaaaaaaaa ) \ + AS2( xor eax, ecx ) \ + AS2( xor ebx, ecx ) \ + AS2( ror eax, 9 ) \ + AS2( mov ecx, ebx ) \ + AS2( xor ecx, eax ) \ + AS2( and ecx, 0x00ff00ff ) \ + AS2( xor eax, ecx ) \ + AS2( xor ebx, ecx ) \ + AS2( rol eax, 6 ) \ + AS2( mov ecx, ebx ) \ + AS2( xor ecx, eax ) \ + AS2( and ecx, 0x33333333 ) \ + AS2( xor eax, ecx ) \ + AS2( xor ebx, ecx ) \ + AS2( rol eax, 18 ) \ + AS2( mov ecx, ebx ) \ + AS2( xor ecx, eax ) \ + AS2( and ecx, 0xffff0000 ) \ + AS2( xor eax, ecx ) \ + AS2( xor ebx, ecx ) \ + AS2( rol eax, 20 ) \ + AS2( mov ecx, ebx ) \ + AS2( xor ecx, eax ) \ + AS2( and ecx, 0xf0f0f0f0 ) \ + AS2( xor eax, ecx ) \ + AS2( xor ebx, ecx ) \ + AS2( ror eax, 4 ) + + + + +/* DesRound implements this algorithm: + + word32 work = rotrFixed(r, 4U) ^ key[0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ key[1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ key[2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ key[3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + left is in aex + right is in ebx + key is in edx + + edvances key for next round + + uses ecx, esi, and edi +*/ +#define DesRound() \ + AS2( mov ecx, ebx )\ + AS2( mov esi, DWORD PTR [edx] )\ + AS2( ror ecx, 4 )\ + AS2( xor ecx, esi )\ + AS2( and ecx, 0x3f3f3f3f )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor eax, [ebp + esi*4 + 6*256] )\ + AS2( shr ecx, 16 )\ + AS2( xor eax, [ebp + edi*4 + 4*256] )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor eax, [ebp + esi*4 + 2*256] )\ + AS2( mov esi, DWORD PTR [edx + 4] )\ + AS2( xor eax, [ebp + edi*4] )\ + AS2( mov ecx, ebx )\ + AS2( xor ecx, esi )\ + AS2( and ecx, 0x3f3f3f3f )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor eax, [ebp + esi*4 + 7*256] )\ + AS2( shr ecx, 16 )\ + AS2( xor eax, [ebp + edi*4 + 5*256] )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor eax, [ebp + esi*4 + 3*256] )\ + AS2( mov esi, DWORD PTR [edx + 8] )\ + AS2( xor eax, [ebp + edi*4 + 1*256] )\ + AS2( mov ecx, eax )\ + AS2( ror ecx, 4 )\ + AS2( xor ecx, esi )\ + AS2( and ecx, 0x3f3f3f3f )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor ebx, [ebp + esi*4 + 6*256] )\ + AS2( shr ecx, 16 )\ + AS2( xor ebx, [ebp + edi*4 + 4*256] )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor ebx, [ebp + esi*4 + 2*256] )\ + AS2( mov esi, DWORD PTR [edx + 12] )\ + AS2( xor ebx, [ebp + edi*4] )\ + AS2( mov ecx, eax )\ + AS2( xor ecx, esi )\ + AS2( and ecx, 0x3f3f3f3f )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor ebx, [ebp + esi*4 + 7*256] )\ + AS2( shr ecx, 16 )\ + AS2( xor ebx, [ebp + edi*4 + 5*256] )\ + AS2( movzx esi, cl )\ + AS2( movzx edi, ch )\ + AS2( xor ebx, [ebp + esi*4 + 3*256] )\ + AS2( add edx, 16 )\ + AS2( xor ebx, [ebp + edi*4 + 1*256] ) + + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void DES_EDE3::AsmProcess(const byte* in, byte* out, void* box) const +{ +#ifdef __GNUC__ + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + + #define PROLOG() \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + "push ebx;" \ + "push ebp;" \ + "movd mm6, ebp;" \ + "movd mm7, ecx;" \ + "mov ebp, eax;" + #define EPILOG() \ + "pop ebp;" \ + "pop ebx;" \ + "emms;" \ + ".att_syntax;" \ + : \ + : "d" (this), "S" (in), "a" (box), "c" (out) \ + : "%edi", "memory", "cc" \ + ); + +#else + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + + #define PROLOG() \ + AS1( push ebp ) \ + AS2( mov ebp, esp ) \ + AS2( movd mm3, edi ) \ + AS2( movd mm4, ebx ) \ + AS2( movd mm5, esi ) \ + AS2( movd mm6, ebp ) \ + AS2( mov esi, DWORD PTR [ebp + 8] ) \ + AS2( mov edx, ecx ) \ + AS2( mov ebp, DWORD PTR [ebp + 16] ) + + // ebp restored at end + #define EPILOG() \ + AS2( movd edi, mm3 ) \ + AS2( movd ebx, mm4 ) \ + AS2( movd esi, mm5 ) \ + AS2( mov esp, ebp ) \ + AS1( pop ebp ) \ + AS1( emms ) \ + AS1( ret 12 ) + +#endif + + + PROLOG() + + AS2( movd mm2, edx ) + + #ifdef OLD_GCC_OFFSET + AS2( add edx, 60 ) // des1 = des1 key + #else + AS2( add edx, 56 ) // des1 = des1 key + #endif + + AS2( mov eax, DWORD PTR [esi] ) + AS2( mov ebx, DWORD PTR [esi + 4] ) + AS1( bswap eax ) // left + AS1( bswap ebx ) // right + + AsmIPERM() + + DesRound() // 1 + DesRound() // 2 + DesRound() // 3 + DesRound() // 4 + DesRound() // 5 + DesRound() // 6 + DesRound() // 7 + DesRound() // 8 + + // swap left and right + AS2( xchg eax, ebx ) + + DesRound() // 1 + DesRound() // 2 + DesRound() // 3 + DesRound() // 4 + DesRound() // 5 + DesRound() // 6 + DesRound() // 7 + DesRound() // 8 + + // swap left and right + AS2( xchg eax, ebx ) + + DesRound() // 1 + DesRound() // 2 + DesRound() // 3 + DesRound() // 4 + DesRound() // 5 + DesRound() // 6 + DesRound() // 7 + DesRound() // 8 + + AsmFPERM() + + //end + AS2( movd ebp, mm6 ) + + // swap and write out + AS1( bswap ebx ) + AS1( bswap eax ) + +#ifdef __GNUC__ + AS2( movd esi, mm7 ) // outBlock +#else + AS2( mov esi, DWORD PTR [ebp + 12] ) // outBlock +#endif + + AS2( mov DWORD PTR [esi], ebx ) // right first + AS2( mov DWORD PTR [esi + 4], eax ) + + + EPILOG() +} + + + +#endif // defined(DO_DES_ASM) + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/dh.cpp b/mysql/extra/yassl/taocrypt/src/dh.cpp new file mode 100644 index 0000000..615a8c6 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/dh.cpp @@ -0,0 +1,103 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* dh.cpp implements Diffie-Hellman support +*/ + +#include "runtime.hpp" +#include "dh.hpp" +#include "asn.hpp" +#include + +namespace TaoCrypt { + + +namespace { // locals + +unsigned int DiscreteLogWorkFactor(unsigned int n) +{ + // assuming discrete log takes about the same time as factoring + if (n<5) + return 0; + else + return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * + pow(log(double(n)), 2.0/3.0) - 5); +} + +} // namespace locals + + +// Generate a DH Key Pair +void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub) +{ + GeneratePrivate(rng, priv); + GeneratePublic(priv, pub); +} + + +// Generate private value +void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv) +{ + Integer x(rng, Integer::One(), min(p_ - 1, + Integer::Power2(2*DiscreteLogWorkFactor(p_.BitCount())) ) ); + x.Encode(priv, p_.ByteCount()); +} + + +// Generate public value +void DH::GeneratePublic(const byte* priv, byte* pub) +{ + const word32 bc(p_.ByteCount()); + Integer x(priv, bc); + Integer y(a_exp_b_mod_c(g_, x, p_)); + y.Encode(pub, bc); +} + + +// Generate Agreement +void DH::Agree(byte* agree, const byte* priv, const byte* otherPub, word32 + otherSz) +{ + const word32 bc(p_.ByteCount()); + Integer x(priv, bc); + Integer y; + if (otherSz) + y.Decode(otherPub, otherSz); + else + y.Decode(otherPub, bc); + + Integer z(a_exp_b_mod_c(y, x, p_)); + z.Encode(agree, bc); +} + + +DH::DH(Source& source) +{ + Initialize(source); +} + + +void DH::Initialize(Source& source) +{ + DH_Decoder decoder(source); + decoder.Decode(*this); +} + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/dsa.cpp b/mysql/extra/yassl/taocrypt/src/dsa.cpp new file mode 100644 index 0000000..b19fed9 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/dsa.cpp @@ -0,0 +1,274 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +#include "runtime.hpp" +#include "dsa.hpp" +#include "sha.hpp" +#include "asn.hpp" +#include "modarith.hpp" + + +namespace TaoCrypt { + + +void DSA_PublicKey::Swap(DSA_PublicKey& other) +{ + p_.Swap(other.p_); + q_.Swap(other.q_); + g_.Swap(other.g_); + y_.Swap(other.y_); +} + + +DSA_PublicKey::DSA_PublicKey(const DSA_PublicKey& other) + : p_(other.p_), q_(other.q_), g_(other.g_), y_(other.y_) +{} + + +DSA_PublicKey& DSA_PublicKey::operator=(const DSA_PublicKey& that) +{ + DSA_PublicKey tmp(that); + Swap(tmp); + return *this; +} + + +DSA_PublicKey::DSA_PublicKey(Source& source) +{ + Initialize(source); +} + + +void DSA_PublicKey::Initialize(Source& source) +{ + DSA_Public_Decoder decoder(source); + decoder.Decode(*this); +} + + +void DSA_PublicKey::Initialize(const Integer& p, const Integer& q, + const Integer& g, const Integer& y) +{ + p_ = p; + q_ = q; + g_ = g; + y_ = y; +} + + +const Integer& DSA_PublicKey::GetModulus() const +{ + return p_; +} + +const Integer& DSA_PublicKey::GetSubGroupOrder() const +{ + return q_; +} + + +const Integer& DSA_PublicKey::GetSubGroupGenerator() const +{ + return g_; +} + + +const Integer& DSA_PublicKey::GetPublicPart() const +{ + return y_; +} + + +void DSA_PublicKey::SetModulus(const Integer& p) +{ + p_ = p; +} + + +void DSA_PublicKey::SetSubGroupOrder(const Integer& q) +{ + q_ = q; +} + + +void DSA_PublicKey::SetSubGroupGenerator(const Integer& g) +{ + g_ = g; +} + + +void DSA_PublicKey::SetPublicPart(const Integer& y) +{ + y_ = y; +} + + +word32 DSA_PublicKey::SignatureLength() const +{ + return GetSubGroupOrder().ByteCount() * 2; // r and s +} + + + +DSA_PrivateKey::DSA_PrivateKey(Source& source) +{ + Initialize(source); +} + + +void DSA_PrivateKey::Initialize(Source& source) +{ + DSA_Private_Decoder decoder(source); + decoder.Decode(*this); +} + + +void DSA_PrivateKey::Initialize(const Integer& p, const Integer& q, + const Integer& g, const Integer& y, + const Integer& x) +{ + DSA_PublicKey::Initialize(p, q, g, y); + x_ = x; +} + + +const Integer& DSA_PrivateKey::GetPrivatePart() const +{ + return x_; +} + + +void DSA_PrivateKey::SetPrivatePart(const Integer& x) +{ + x_ = x; +} + + +DSA_Signer::DSA_Signer(const DSA_PrivateKey& key) + : key_(key) +{} + + +word32 DSA_Signer::Sign(const byte* sha_digest, byte* sig, + RandomNumberGenerator& rng) +{ + const Integer& p = key_.GetModulus(); + const Integer& q = key_.GetSubGroupOrder(); + const Integer& g = key_.GetSubGroupGenerator(); + const Integer& x = key_.GetPrivatePart(); + byte* tmpPtr = sig; // initial signature output + + Integer k(rng, 1, q - 1); + + r_ = a_exp_b_mod_c(g, k, p); + r_ %= q; + + Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m) + + Integer kInv = k.InverseMod(q); + s_ = (kInv * (H + x*r_)) % q; + + if (!(!!r_ && !!s_)) + return -1; + + int rSz = r_.ByteCount(); + int tmpSz = rSz; + + while (tmpSz++ < SHA::DIGEST_SIZE) { + *sig++ = 0; + } + + r_.Encode(sig, rSz); + + sig = tmpPtr + SHA::DIGEST_SIZE; // advance sig output to s + int sSz = s_.ByteCount(); + tmpSz = sSz; + + while (tmpSz++ < SHA::DIGEST_SIZE) { + *sig++ = 0; + } + + s_.Encode(sig, sSz); + + return 40; +} + + +DSA_Verifier::DSA_Verifier(const DSA_PublicKey& key) + : key_(key) +{} + + +bool DSA_Verifier::Verify(const byte* sha_digest, const byte* sig) +{ + const Integer& p = key_.GetModulus(); + const Integer& q = key_.GetSubGroupOrder(); + const Integer& g = key_.GetSubGroupGenerator(); + const Integer& y = key_.GetPublicPart(); + + int sz = q.ByteCount(); + + r_.Decode(sig, sz); + s_.Decode(sig + sz, sz); + + if (r_ >= q || r_ < 1 || s_ >= q || s_ < 1) + return false; + + Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m) + + Integer w = s_.InverseMod(q); + Integer u1 = (H * w) % q; + Integer u2 = (r_ * w) % q; + + // verify r == ((g^u1 * y^u2) mod p) mod q + ModularArithmetic ma(p); + Integer v = ma.CascadeExponentiate(g, u1, y, u2); + v %= q; + + return r_ == v; +} + + + + +const Integer& DSA_Signer::GetR() const +{ + return r_; +} + + +const Integer& DSA_Signer::GetS() const +{ + return s_; +} + + +const Integer& DSA_Verifier::GetR() const +{ + return r_; +} + + +const Integer& DSA_Verifier::GetS() const +{ + return s_; +} + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/file.cpp b/mysql/extra/yassl/taocrypt/src/file.cpp new file mode 100644 index 0000000..7c2044b --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/file.cpp @@ -0,0 +1,115 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* file.cpp implements File Sources and Sinks +*/ + +#include "runtime.hpp" +#include "file.hpp" + + +namespace TaoCrypt { + + +FileSource::FileSource(const char* fname, Source& source) +{ + file_ = fopen(fname, "rb"); + if (file_) get(source); +} + + +FileSource::~FileSource() +{ + if (file_) + fclose(file_); +} + + + +// return size of source from beginning or current position +word32 FileSource::size(bool use_current) +{ + long current = ftell(file_); + long begin = current; + + if (!use_current) { + fseek(file_, 0, SEEK_SET); + begin = ftell(file_); + } + + fseek(file_, 0, SEEK_END); + long end = ftell(file_); + + fseek(file_, current, SEEK_SET); + + return end - begin; +} + + +word32 FileSource::size_left() +{ + return size(true); +} + + +// fill file source from source +word32 FileSource::get(Source& source) +{ + word32 sz(size()); + if (source.size() < sz) + source.grow(sz); + + size_t bytes = fread(source.buffer_.get_buffer(), 1, sz, file_); + + if (bytes == 1) + return sz; + else + return 0; +} + + +FileSink::FileSink(const char* fname, Source& source) +{ + file_ = fopen(fname, "wb"); + if (file_) put(source); +} + + +FileSink::~FileSink() +{ + if (file_) + fclose(file_); +} + + +// fill source from file sink +void FileSink::put(Source& source) +{ + fwrite(source.get_buffer(), 1, source.size(), file_); +} + + +// swap with other and reset to beginning +void Source::reset(ByteBlock& otherBlock) +{ + buffer_.Swap(otherBlock); + current_ = 0; +} + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/hash.cpp b/mysql/extra/yassl/taocrypt/src/hash.cpp new file mode 100644 index 0000000..c176e6a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/hash.cpp @@ -0,0 +1,191 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* hash.cpp implements a base for digest types +*/ + +#include "runtime.hpp" +#include + +#include "hash.hpp" + + +namespace TaoCrypt { + + +HASHwithTransform::HASHwithTransform(word32 digSz, word32 buffSz) +{ +} + + +void HASHwithTransform::AddLength(word32 len) +{ + HashLengthType tmp = loLen_; + if ( (loLen_ += len) < tmp) + hiLen_++; // carry low to high + hiLen_ += SafeRightShift<8*sizeof(HashLengthType)>(len); +} + + +// Update digest with data of size len, do in blocks +void HASHwithTransform::Update(const byte* data, word32 len) +{ + // do block size increments + word32 blockSz = getBlockSize(); + byte* local = reinterpret_cast(buffer_); + + while (len) { + word32 add = min(len, blockSz - buffLen_); + memcpy(&local[buffLen_], data, add); + + buffLen_ += add; + data += add; + len -= add; + + if (buffLen_ == blockSz) { + ByteReverseIf(local, local, blockSz, getByteOrder()); + Transform(); + AddLength(blockSz); + buffLen_ = 0; + } + } +} + + +// Final process, place digest in hash +void HASHwithTransform::Final(byte* hash) +{ + word32 blockSz = getBlockSize(); + word32 digestSz = getDigestSize(); + word32 padSz = getPadSize(); + ByteOrder order = getByteOrder(); + + AddLength(buffLen_); // before adding pads + HashLengthType preLoLen = GetBitCountLo(); + HashLengthType preHiLen = GetBitCountHi(); + byte* local = reinterpret_cast(buffer_); + + local[buffLen_++] = 0x80; // add 1 + + // pad with zeros + if (buffLen_ > padSz) { + memset(&local[buffLen_], 0, blockSz - buffLen_); + buffLen_ += blockSz - buffLen_; + + ByteReverseIf(local, local, blockSz, order); + Transform(); + buffLen_ = 0; + } + memset(&local[buffLen_], 0, padSz - buffLen_); + + ByteReverseIf(local, local, blockSz, order); + + memcpy(&local[padSz], order ? &preHiLen : &preLoLen, sizeof(preLoLen)); + memcpy(&local[padSz+4], order ? &preLoLen : &preHiLen, sizeof(preLoLen)); + + Transform(); + ByteReverseIf(digest_, digest_, digestSz, order); + memcpy(hash, digest_, digestSz); + + Init(); // reset state +} + + +#ifdef WORD64_AVAILABLE + +HASH64withTransform::HASH64withTransform(word32 digSz, word32 buffSz) +{ +} + + +void HASH64withTransform::AddLength(word32 len) +{ + HashLengthType tmp = loLen_; + if ( (loLen_ += len) < tmp) + hiLen_++; // carry low to high + hiLen_ += SafeRightShift<8*sizeof(HashLengthType)>(len); +} + + +// Update digest with data of size len, do in blocks +void HASH64withTransform::Update(const byte* data, word32 len) +{ + // do block size increments + word32 blockSz = getBlockSize(); + byte* local = reinterpret_cast(buffer_); + + while (len) { + word32 add = min(len, blockSz - buffLen_); + memcpy(&local[buffLen_], data, add); + + buffLen_ += add; + data += add; + len -= add; + + if (buffLen_ == blockSz) { + ByteReverseIf(buffer_, buffer_, blockSz, getByteOrder()); + Transform(); + AddLength(blockSz); + buffLen_ = 0; + } + } +} + + +// Final process, place digest in hash +void HASH64withTransform::Final(byte* hash) +{ + word32 blockSz = getBlockSize(); + word32 digestSz = getDigestSize(); + word32 padSz = getPadSize(); + ByteOrder order = getByteOrder(); + + AddLength(buffLen_); // before adding pads + HashLengthType preLoLen = GetBitCountLo(); + HashLengthType preHiLen = GetBitCountHi(); + byte* local = reinterpret_cast(buffer_); + + local[buffLen_++] = 0x80; // add 1 + + // pad with zeros + if (buffLen_ > padSz) { + memset(&local[buffLen_], 0, blockSz - buffLen_); + buffLen_ += blockSz - buffLen_; + + ByteReverseIf(buffer_, buffer_, blockSz, order); + Transform(); + buffLen_ = 0; + } + memset(&local[buffLen_], 0, padSz - buffLen_); + + ByteReverseIf(buffer_, buffer_, padSz, order); + + buffer_[blockSz / sizeof(word64) - 2] = order ? preHiLen : preLoLen; + buffer_[blockSz / sizeof(word64) - 1] = order ? preLoLen : preHiLen; + + Transform(); + ByteReverseIf(digest_, digest_, digestSz, order); + memcpy(hash, digest_, digestSz); + + Init(); // reset state +} + +#endif // WORD64_AVAILABLE + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/hc128.cpp b/mysql/extra/yassl/taocrypt/src/hc128.cpp new file mode 100644 index 0000000..1d329c8 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/hc128.cpp @@ -0,0 +1,317 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +#include "runtime.hpp" +#include "hc128.hpp" + + + +namespace TaoCrypt { + + + + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverse((word32)x) +#else + #define LITTLE32(x) (x) +#endif + + +/*h1 function*/ +#define h1(x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (T_[512+a])+(T_[512+256+c]); \ +} + +/*h2 function*/ +#define h2(x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (T_[a])+(T_[256+c]); \ +} + +/*one step of HC-128, update P and generate 32 bits keystream*/ +#define step_P(u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h1((X_[(d)]),tem3); \ + tem0 = rotrFixed((T_[(v)]),23); \ + tem1 = rotrFixed((X_[(c)]),10); \ + tem2 = rotrFixed((X_[(b)]),8); \ + (T_[(u)]) += tem2+(tem0 ^ tem1); \ + (X_[(a)]) = (T_[(u)]); \ + (n) = tem3 ^ (T_[(u)]) ; \ +} + +/*one step of HC-128, update Q and generate 32 bits keystream*/ +#define step_Q(u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h2((Y_[(d)]),tem3); \ + tem0 = rotrFixed((T_[(v)]),(32-23)); \ + tem1 = rotrFixed((Y_[(c)]),(32-10)); \ + tem2 = rotrFixed((Y_[(b)]),(32-8)); \ + (T_[(u)]) += tem2 + (tem0 ^ tem1); \ + (Y_[(a)]) = (T_[(u)]); \ + (n) = tem3 ^ (T_[(u)]) ; \ +} + + +/*16 steps of HC-128, generate 512 bits keystream*/ +void HC128::GenerateKeystream(word32* keystream) +{ + word32 cc,dd; + cc = counter1024_ & 0x1ff; + dd = (cc+16)&0x1ff; + + if (counter1024_ < 512) + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + step_P(cc+0, cc+1, 0, 6, 13,4, keystream[0]); + step_P(cc+1, cc+2, 1, 7, 14,5, keystream[1]); + step_P(cc+2, cc+3, 2, 8, 15,6, keystream[2]); + step_P(cc+3, cc+4, 3, 9, 0, 7, keystream[3]); + step_P(cc+4, cc+5, 4, 10,1, 8, keystream[4]); + step_P(cc+5, cc+6, 5, 11,2, 9, keystream[5]); + step_P(cc+6, cc+7, 6, 12,3, 10,keystream[6]); + step_P(cc+7, cc+8, 7, 13,4, 11,keystream[7]); + step_P(cc+8, cc+9, 8, 14,5, 12,keystream[8]); + step_P(cc+9, cc+10,9, 15,6, 13,keystream[9]); + step_P(cc+10,cc+11,10,0, 7, 14,keystream[10]); + step_P(cc+11,cc+12,11,1, 8, 15,keystream[11]); + step_P(cc+12,cc+13,12,2, 9, 0, keystream[12]); + step_P(cc+13,cc+14,13,3, 10,1, keystream[13]); + step_P(cc+14,cc+15,14,4, 11,2, keystream[14]); + step_P(cc+15,dd+0, 15,5, 12,3, keystream[15]); + } + else + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + step_Q(512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); + step_Q(512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]); + step_Q(512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]); + step_Q(512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]); + step_Q(512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]); + step_Q(512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]); + step_Q(512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]); + step_Q(512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]); + step_Q(512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]); + step_Q(512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]); + step_Q(512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]); + step_Q(512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]); + step_Q(512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]); + step_Q(512+cc+13,512+cc+14,13,3, 10,1, keystream[13]); + step_Q(512+cc+14,512+cc+15,14,4, 11,2, keystream[14]); + step_Q(512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]); + } +} + + +/* The following defines the initialization functions */ +#define f1(x) (rotrFixed((x),7) ^ rotrFixed((x),18) ^ ((x) >> 3)) +#define f2(x) (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10)) + +/*update table P*/ +#define update_P(u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrFixed((T_[(v)]),23); \ + tem1 = rotrFixed((X_[(c)]),10); \ + tem2 = rotrFixed((X_[(b)]),8); \ + h1((X_[(d)]),tem3); \ + (T_[(u)]) = ((T_[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (X_[(a)]) = (T_[(u)]); \ +} + +/*update table Q*/ +#define update_Q(u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrFixed((T_[(v)]),(32-23)); \ + tem1 = rotrFixed((Y_[(c)]),(32-10)); \ + tem2 = rotrFixed((Y_[(b)]),(32-8)); \ + h2((Y_[(d)]),tem3); \ + (T_[(u)]) = ((T_[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (Y_[(a)]) = (T_[(u)]); \ +} + +/*16 steps of HC-128, without generating keystream, */ +/*but use the outputs to update P and Q*/ +void HC128::SetupUpdate() /*each time 16 steps*/ +{ + word32 cc,dd; + cc = counter1024_ & 0x1ff; + dd = (cc+16)&0x1ff; + + if (counter1024_ < 512) + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + update_P(cc+0, cc+1, 0, 6, 13, 4); + update_P(cc+1, cc+2, 1, 7, 14, 5); + update_P(cc+2, cc+3, 2, 8, 15, 6); + update_P(cc+3, cc+4, 3, 9, 0, 7); + update_P(cc+4, cc+5, 4, 10,1, 8); + update_P(cc+5, cc+6, 5, 11,2, 9); + update_P(cc+6, cc+7, 6, 12,3, 10); + update_P(cc+7, cc+8, 7, 13,4, 11); + update_P(cc+8, cc+9, 8, 14,5, 12); + update_P(cc+9, cc+10,9, 15,6, 13); + update_P(cc+10,cc+11,10,0, 7, 14); + update_P(cc+11,cc+12,11,1, 8, 15); + update_P(cc+12,cc+13,12,2, 9, 0); + update_P(cc+13,cc+14,13,3, 10, 1); + update_P(cc+14,cc+15,14,4, 11, 2); + update_P(cc+15,dd+0, 15,5, 12, 3); + } + else + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + update_Q(512+cc+0, 512+cc+1, 0, 6, 13, 4); + update_Q(512+cc+1, 512+cc+2, 1, 7, 14, 5); + update_Q(512+cc+2, 512+cc+3, 2, 8, 15, 6); + update_Q(512+cc+3, 512+cc+4, 3, 9, 0, 7); + update_Q(512+cc+4, 512+cc+5, 4, 10,1, 8); + update_Q(512+cc+5, 512+cc+6, 5, 11,2, 9); + update_Q(512+cc+6, 512+cc+7, 6, 12,3, 10); + update_Q(512+cc+7, 512+cc+8, 7, 13,4, 11); + update_Q(512+cc+8, 512+cc+9, 8, 14,5, 12); + update_Q(512+cc+9, 512+cc+10,9, 15,6, 13); + update_Q(512+cc+10,512+cc+11,10,0, 7, 14); + update_Q(512+cc+11,512+cc+12,11,1, 8, 15); + update_Q(512+cc+12,512+cc+13,12,2, 9, 0); + update_Q(512+cc+13,512+cc+14,13,3, 10, 1); + update_Q(512+cc+14,512+cc+15,14,4, 11, 2); + update_Q(512+cc+15,512+dd+0, 15,5, 12, 3); + } +} + + +/* for the 128-bit key: key[0]...key[15] +* key[0] is the least significant byte of ctx->key[0] (K_0); +* key[3] is the most significant byte of ctx->key[0] (K_0); +* ... +* key[12] is the least significant byte of ctx->key[3] (K_3) +* key[15] is the most significant byte of ctx->key[3] (K_3) +* +* for the 128-bit iv: iv[0]...iv[15] +* iv[0] is the least significant byte of ctx->iv[0] (IV_0); +* iv[3] is the most significant byte of ctx->iv[0] (IV_0); +* ... +* iv[12] is the least significant byte of ctx->iv[3] (IV_3) +* iv[15] is the most significant byte of ctx->iv[3] (IV_3) +*/ + + + +void HC128::SetIV(const byte* iv) +{ + word32 i; + + for (i = 0; i < (128 >> 5); i++) + iv_[i] = LITTLE32(((word32*)iv)[i]); + + for (; i < 8; i++) iv_[i] = iv_[i-4]; + + /* expand the key and IV into the table T */ + /* (expand the key and IV into the table P and Q) */ + + for (i = 0; i < 8; i++) T_[i] = key_[i]; + for (i = 8; i < 16; i++) T_[i] = iv_[i-8]; + + for (i = 16; i < (256+16); i++) + T_[i] = f2(T_[i-2]) + T_[i-7] + f1(T_[i-15]) + T_[i-16]+i; + + for (i = 0; i < 16; i++) T_[i] = T_[256+i]; + + for (i = 16; i < 1024; i++) + T_[i] = f2(T_[i-2]) + T_[i-7] + f1(T_[i-15]) + T_[i-16]+256+i; + + /* initialize counter1024, X and Y */ + counter1024_ = 0; + for (i = 0; i < 16; i++) X_[i] = T_[512-16+i]; + for (i = 0; i < 16; i++) Y_[i] = T_[512+512-16+i]; + + /* run the cipher 1024 steps before generating the output */ + for (i = 0; i < 64; i++) SetupUpdate(); +} + + +void HC128::SetKey(const byte* key, const byte* iv) +{ + word32 i; + + /* Key size in bits 128 */ + for (i = 0; i < (128 >> 5); i++) + key_[i] = LITTLE32(((word32*)key)[i]); + + for ( ; i < 8 ; i++) key_[i] = key_[i-4]; + + SetIV(iv); +} + + +/* The following defines the encryption of data stream */ +void HC128::Process(byte* output, const byte* input, word32 msglen) +{ + word32 i, keystream[16]; + + for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64) + { + GenerateKeystream(keystream); + + /* unroll loop */ + ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); + ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); + ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); + ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); + ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); + ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); + ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); + ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); + ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); + ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); + ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); + ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); + ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); + ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); + ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); + ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); + } + + if (msglen > 0) + { + GenerateKeystream(keystream); + +#ifdef BIG_ENDIAN_ORDER + { + word32 wordsLeft = msglen / sizeof(word32); + if (msglen % sizeof(word32)) wordsLeft++; + + ByteReverse(keystream, keystream, wordsLeft * sizeof(word32)); + } +#endif + + for (i = 0; i < msglen; i++) + output[i] = input[i] ^ ((byte*)keystream)[i]; + } + +} + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/integer.cpp b/mysql/extra/yassl/taocrypt/src/integer.cpp new file mode 100644 index 0000000..478a13c --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/integer.cpp @@ -0,0 +1,3894 @@ +/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +/* based on Wei Dai's integer.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "integer.hpp" +#include "modarith.hpp" +#include "asn.hpp" + + + +#ifdef __DECCXX + #include // for asm overflow assembly +#endif + +#if defined(_M_X64) || defined(_M_IA64) + #include +#pragma intrinsic(_umul128) +#endif + + +#ifdef __GNUC__ + #include + #include +#endif + + +#ifdef SSE2_INTRINSICS_AVAILABLE + #ifdef __GNUC__ + #include + #ifdef TAOCRYPT_MEMALIGN_AVAILABLE + #include + #else + #include + #endif + #else + #include + #endif +#elif defined(_MSC_VER) && defined(_M_IX86) +/* #pragma message("You do not seem to have the Visual C++ Processor Pack ") + #pragma message("installed, so use of SSE2 intrinsics will be disabled.") +*/ + #pragma message("installed, so use of SSE2 intrinsics will be disabled.") +#elif defined(__GNUC__) && defined(__i386__) +/* #warning You do not have GCC 3.3 or later, or did not specify the -msse2 \ + compiler option. Use of SSE2 intrinsics will be disabled. +*/ +#endif + + +namespace TaoCrypt { + + +#ifdef SSE2_INTRINSICS_AVAILABLE + +template +CPP_TYPENAME AlignedAllocator::pointer AlignedAllocator::allocate( + size_type n, const void *) +{ + if (n > this->max_size()) + return 0; + if (n == 0) + return 0; + if (n >= 4) + { + void* p; + #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE + p = _mm_malloc(sizeof(T)*n, 16); + #elif defined(TAOCRYPT_MEMALIGN_AVAILABLE) + p = memalign(16, sizeof(T)*n); + #elif defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16) + p = malloc(sizeof(T)*n); + #else + p = (byte *)malloc(sizeof(T)*n + 8); + // assume malloc alignment is at least 8 + #endif + + #ifdef TAOCRYPT_NO_ALIGNED_ALLOC + m_pBlock = p; + if (!IsAlignedOn(p, 16)) + { + p = (byte *)p + 8; + } + #endif + + return (T*)p; + } + return NEW_TC T[n]; +} + + +template +void AlignedAllocator::deallocate(void* p, size_type n) +{ + memset(p, 0, n*sizeof(T)); + if (n >= 4) + { + #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE + _mm_free(p); + #elif defined(TAOCRYPT_NO_ALIGNED_ALLOC) + free(m_pBlock); + m_pBlock = 0; + #else + free(p); + #endif + } + else + tcArrayDelete((T *)p); +} + +#endif // SSE2 + + +// ******** start of integer needs + +// start 5.2.1 adds DWord and Word ******** + +// ******************************************************** + +class DWord { +public: +DWord() {} + +#ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + explicit DWord(word low) + { + whole_ = low; + } +#else + explicit DWord(word low) + { + halfs_.low = low; + halfs_.high = 0; + } +#endif + + DWord(word low, word high) + { + halfs_.low = low; + halfs_.high = high; + } + + static DWord Multiply(word a, word b) + { + DWord r; + + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + r.whole_ = (dword)a * b; + + #elif defined(_M_X64) || defined(_M_IA64) + r.halfs_.low = _umul128(a, b, &r.halfs_.high); + + #elif defined(__ia64__) + r.halfs_.low = a*b; + __asm__("xmpy.hu %0=%1,%2" : "=f" (r.halfs_.high) + : "f" (a), "f" (b)); + + #elif defined(_ARCH_PPC64) + r.halfs_.low = a*b; + __asm__("mulhdu %0,%1,%2" : "=r" (r.halfs_.high) + : "r" (a), "r" (b) : "cc"); + + #elif defined(__x86_64__) + __asm__("mulq %3" : "=d" (r.halfs_.high), "=a" (r.halfs_.low) : + "a" (a), "rm" (b) : "cc"); + + #elif defined(__mips64) + __asm__("dmultu %2,%3" : "=h" (r.halfs_.high), "=l" (r.halfs_.low) + : "r" (a), "r" (b)); + + #elif defined(_M_IX86) + // for testing + word64 t = (word64)a * b; + r.halfs_.high = ((word32 *)(&t))[1]; + r.halfs_.low = (word32)t; + #else + #error can not implement DWord + #endif + + return r; + } + + static DWord MultiplyAndAdd(word a, word b, word c) + { + DWord r = Multiply(a, b); + return r += c; + } + + DWord & operator+=(word a) + { + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + whole_ = whole_ + a; + #else + halfs_.low += a; + halfs_.high += (halfs_.low < a); + #endif + return *this; + } + + DWord operator+(word a) + { + DWord r; + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + r.whole_ = whole_ + a; + #else + r.halfs_.low = halfs_.low + a; + r.halfs_.high = halfs_.high + (r.halfs_.low < a); + #endif + return r; + } + + DWord operator-(DWord a) + { + DWord r; + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + r.whole_ = whole_ - a.whole_; + #else + r.halfs_.low = halfs_.low - a.halfs_.low; + r.halfs_.high = halfs_.high - a.halfs_.high - + (r.halfs_.low > halfs_.low); + #endif + return r; + } + + DWord operator-(word a) + { + DWord r; + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + r.whole_ = whole_ - a; + #else + r.halfs_.low = halfs_.low - a; + r.halfs_.high = halfs_.high - (r.halfs_.low > halfs_.low); + #endif + return r; + } + + // returns quotient, which must fit in a word + word operator/(word divisor); + + word operator%(word a); + + bool operator!() const + { + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + return !whole_; + #else + return !halfs_.high && !halfs_.low; + #endif + } + + word GetLowHalf() const {return halfs_.low;} + word GetHighHalf() const {return halfs_.high;} + word GetHighHalfAsBorrow() const {return 0-halfs_.high;} + +private: + struct dword_struct + { + #ifdef LITTLE_ENDIAN_ORDER + word low; + word high; + #else + word high; + word low; + #endif + }; + + union + { + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + dword whole_; + #endif + struct dword_struct halfs_; + }; +}; + + +class Word { +public: + Word() {} + + Word(word value) + { + whole_ = value; + } + + Word(hword low, hword high) + { + whole_ = low | (word(high) << (WORD_BITS/2)); + } + + static Word Multiply(hword a, hword b) + { + Word r; + r.whole_ = (word)a * b; + return r; + } + + Word operator-(Word a) + { + Word r; + r.whole_ = whole_ - a.whole_; + return r; + } + + Word operator-(hword a) + { + Word r; + r.whole_ = whole_ - a; + return r; + } + + // returns quotient, which must fit in a word + hword operator/(hword divisor) + { + return hword(whole_ / divisor); + } + + bool operator!() const + { + return !whole_; + } + + word GetWhole() const {return whole_;} + hword GetLowHalf() const {return hword(whole_);} + hword GetHighHalf() const {return hword(whole_>>(WORD_BITS/2));} + hword GetHighHalfAsBorrow() const {return 0-hword(whole_>>(WORD_BITS/2));} + +private: + word whole_; +}; + + +// dummy is VC60 compiler bug workaround +// do a 3 word by 2 word divide, returns quotient and leaves remainder in A +template +S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0) +{ + // estimate the quotient: do a 2 S by 1 S divide + S Q; + if (S(B1+1) == 0) + Q = A[2]; + else + Q = D(A[1], A[2]) / S(B1+1); + + // now subtract Q*B from A + D p = D::Multiply(B0, Q); + D u = (D) A[0] - p.GetLowHalf(); + A[0] = u.GetLowHalf(); + u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - + D::Multiply(B1, Q); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + + // Q <= actual quotient, so fix it + while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) + { + u = (D) A[0] - B0; + A[0] = u.GetLowHalf(); + u = (D) A[1] - B1 - u.GetHighHalfAsBorrow(); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + Q++; + } + + return Q; +} + + +// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 +template +inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B) +{ + if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) + return D(Ah.GetLowHalf(), Ah.GetHighHalf()); + else + { + S Q[2]; + T[0] = Al.GetLowHalf(); + T[1] = Al.GetHighHalf(); + T[2] = Ah.GetLowHalf(); + T[3] = Ah.GetHighHalf(); + Q[1] = DivideThreeWordsByTwo(T+1, B.GetLowHalf(), + B.GetHighHalf()); + Q[0] = DivideThreeWordsByTwo(T, B.GetLowHalf(), B.GetHighHalf()); + return D(Q[0], Q[1]); + } +} + + +// returns quotient, which must fit in a word +inline word DWord::operator/(word a) +{ + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + return word(whole_ / a); + #else + hword r[4]; + return DivideFourWordsByTwo(r, halfs_.low, + halfs_.high, a).GetWhole(); + #endif +} + +inline word DWord::operator%(word a) +{ + #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE + return word(whole_ % a); + #else + if (a < (word(1) << (WORD_BITS/2))) + { + hword h = hword(a); + word r = halfs_.high % h; + r = ((halfs_.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h; + return hword((hword(halfs_.low) + (r << (WORD_BITS/2))) % h); + } + else + { + hword r[4]; + DivideFourWordsByTwo(r, halfs_.low, halfs_.high, a); + return Word(r[0], r[1]).GetWhole(); + } + #endif +} + + + +// end 5.2.1 DWord and Word adds + + + + + +static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8}; + +static inline unsigned int RoundupSize(unsigned int n) +{ + if (n<=8) + return RoundupSizeTable[n]; + else if (n<=16) + return 16; + else if (n<=32) + return 32; + else if (n<=64) + return 64; + else return 1U << BitPrecision(n-1); +} + + +static int Compare(const word *A, const word *B, unsigned int N) +{ + while (N--) + if (A[N] > B[N]) + return 1; + else if (A[N] < B[N]) + return -1; + + return 0; +} + +static word Increment(word *A, unsigned int N, word B=1) +{ + word t = A[0]; + A[0] = t+B; + if (A[0] >= t) + return 0; + for (unsigned i=1; i= A0) + if (B0 >= B1) + { + s = 0; + d = (dword)(A1-A0)*(B0-B1); + } + else + { + s = (A1-A0); + d = (dword)s*(word)(B0-B1); + } + else + if (B0 > B1) + { + s = (B0-B1); + d = (word)(A1-A0)*(dword)s; + } + else + { + s = 0; + d = (dword)(A0-A1)*(B1-B0); + } +*/ + // this segment is the branchless equivalent of above + word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]}; + unsigned int ai = A[1] < A[0]; + unsigned int bi = B[0] < B[1]; + unsigned int di = ai & bi; + DWord d = DWord::Multiply(D[di], D[di+2]); + D[1] = D[3] = 0; + unsigned int si = ai + !bi; + word s = D[si]; + + DWord A0B0 = DWord::Multiply(A[0], B[0]); + C[0] = A0B0.GetLowHalf(); + + DWord A1B1 = DWord::Multiply(A[1], B[1]); + DWord t = (DWord) A0B0.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() + + A1B1.GetLowHalf(); + C[1] = t.GetLowHalf(); + + t = A1B1 + t.GetHighHalf() + A0B0.GetHighHalf() + d.GetHighHalf() + + A1B1.GetHighHalf() - s; + C[2] = t.GetLowHalf(); + C[3] = t.GetHighHalf(); +} + +void Portable::Multiply2Bottom(word *C, const word *A, const word *B) +{ + DWord t = DWord::Multiply(A[0], B[0]); + C[0] = t.GetLowHalf(); + C[1] = t.GetHighHalf() + A[0]*B[1] + A[1]*B[0]; +} + +word Portable::Multiply2Add(word *C, const word *A, const word *B) +{ + word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]}; + unsigned int ai = A[1] < A[0]; + unsigned int bi = B[0] < B[1]; + unsigned int di = ai & bi; + DWord d = DWord::Multiply(D[di], D[di+2]); + D[1] = D[3] = 0; + unsigned int si = ai + !bi; + word s = D[si]; + + DWord A0B0 = DWord::Multiply(A[0], B[0]); + DWord t = A0B0 + C[0]; + C[0] = t.GetLowHalf(); + + DWord A1B1 = DWord::Multiply(A[1], B[1]); + t = (DWord) t.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() + + A1B1.GetLowHalf() + C[1]; + C[1] = t.GetLowHalf(); + + t = (DWord) t.GetHighHalf() + A1B1.GetLowHalf() + A0B0.GetHighHalf() + + d.GetHighHalf() + A1B1.GetHighHalf() - s + C[2]; + C[2] = t.GetLowHalf(); + + t = (DWord) t.GetHighHalf() + A1B1.GetHighHalf() + C[3]; + C[3] = t.GetLowHalf(); + return t.GetHighHalf(); +} + + +#define MulAcc(x, y) \ + p = DWord::MultiplyAndAdd(A[x], B[y], c); \ + c = p.GetLowHalf(); \ + p = (DWord) d + p.GetHighHalf(); \ + d = p.GetLowHalf(); \ + e += p.GetHighHalf(); + +#define SaveMulAcc(s, x, y) \ + R[s] = c; \ + p = DWord::MultiplyAndAdd(A[x], B[y], d); \ + c = p.GetLowHalf(); \ + p = (DWord) e + p.GetHighHalf(); \ + d = p.GetLowHalf(); \ + e = p.GetHighHalf(); + +#define SquAcc(x, y) \ + q = DWord::Multiply(A[x], A[y]); \ + p = q + c; \ + c = p.GetLowHalf(); \ + p = (DWord) d + p.GetHighHalf(); \ + d = p.GetLowHalf(); \ + e += p.GetHighHalf(); \ + p = q + c; \ + c = p.GetLowHalf(); \ + p = (DWord) d + p.GetHighHalf(); \ + d = p.GetLowHalf(); \ + e += p.GetHighHalf(); + +#define SaveSquAcc(s, x, y) \ + R[s] = c; \ + q = DWord::Multiply(A[x], A[y]); \ + p = q + d; \ + c = p.GetLowHalf(); \ + p = (DWord) e + p.GetHighHalf(); \ + d = p.GetLowHalf(); \ + e = p.GetHighHalf(); \ + p = q + c; \ + c = p.GetLowHalf(); \ + p = (DWord) d + p.GetHighHalf(); \ + d = p.GetLowHalf(); \ + e += p.GetHighHalf(); + + +void Portable::Multiply4(word *R, const word *A, const word *B) +{ + DWord p; + word c, d, e; + + p = DWord::Multiply(A[0], B[0]); + R[0] = p.GetLowHalf(); + c = p.GetHighHalf(); + d = e = 0; + + MulAcc(0, 1); + MulAcc(1, 0); + + SaveMulAcc(1, 2, 0); + MulAcc(1, 1); + MulAcc(0, 2); + + SaveMulAcc(2, 0, 3); + MulAcc(1, 2); + MulAcc(2, 1); + MulAcc(3, 0); + + SaveMulAcc(3, 3, 1); + MulAcc(2, 2); + MulAcc(1, 3); + + SaveMulAcc(4, 2, 3); + MulAcc(3, 2); + + R[5] = c; + p = DWord::MultiplyAndAdd(A[3], B[3], d); + R[6] = p.GetLowHalf(); + R[7] = e + p.GetHighHalf(); +} + +void Portable::Square2(word *R, const word *A) +{ + DWord p, q; + word c, d, e; + + p = DWord::Multiply(A[0], A[0]); + R[0] = p.GetLowHalf(); + c = p.GetHighHalf(); + d = e = 0; + + SquAcc(0, 1); + + R[1] = c; + p = DWord::MultiplyAndAdd(A[1], A[1], d); + R[2] = p.GetLowHalf(); + R[3] = e + p.GetHighHalf(); +} + +void Portable::Square4(word *R, const word *A) +{ +#ifdef _MSC_VER + // VC60 workaround: MSVC 6.0 has an optimization bug that makes + // (dword)A*B where either A or B has been cast to a dword before + // very expensive. Revisit this function when this + // bug is fixed. + Multiply4(R, A, A); +#else + const word *B = A; + DWord p, q; + word c, d, e; + + p = DWord::Multiply(A[0], A[0]); + R[0] = p.GetLowHalf(); + c = p.GetHighHalf(); + d = e = 0; + + SquAcc(0, 1); + + SaveSquAcc(1, 2, 0); + MulAcc(1, 1); + + SaveSquAcc(2, 0, 3); + SquAcc(1, 2); + + SaveSquAcc(3, 3, 1); + MulAcc(2, 2); + + SaveSquAcc(4, 2, 3); + + R[5] = c; + p = DWord::MultiplyAndAdd(A[3], A[3], d); + R[6] = p.GetLowHalf(); + R[7] = e + p.GetHighHalf(); +#endif +} + +void Portable::Multiply8(word *R, const word *A, const word *B) +{ + DWord p; + word c, d, e; + + p = DWord::Multiply(A[0], B[0]); + R[0] = p.GetLowHalf(); + c = p.GetHighHalf(); + d = e = 0; + + MulAcc(0, 1); + MulAcc(1, 0); + + SaveMulAcc(1, 2, 0); + MulAcc(1, 1); + MulAcc(0, 2); + + SaveMulAcc(2, 0, 3); + MulAcc(1, 2); + MulAcc(2, 1); + MulAcc(3, 0); + + SaveMulAcc(3, 0, 4); + MulAcc(1, 3); + MulAcc(2, 2); + MulAcc(3, 1); + MulAcc(4, 0); + + SaveMulAcc(4, 0, 5); + MulAcc(1, 4); + MulAcc(2, 3); + MulAcc(3, 2); + MulAcc(4, 1); + MulAcc(5, 0); + + SaveMulAcc(5, 0, 6); + MulAcc(1, 5); + MulAcc(2, 4); + MulAcc(3, 3); + MulAcc(4, 2); + MulAcc(5, 1); + MulAcc(6, 0); + + SaveMulAcc(6, 0, 7); + MulAcc(1, 6); + MulAcc(2, 5); + MulAcc(3, 4); + MulAcc(4, 3); + MulAcc(5, 2); + MulAcc(6, 1); + MulAcc(7, 0); + + SaveMulAcc(7, 1, 7); + MulAcc(2, 6); + MulAcc(3, 5); + MulAcc(4, 4); + MulAcc(5, 3); + MulAcc(6, 2); + MulAcc(7, 1); + + SaveMulAcc(8, 2, 7); + MulAcc(3, 6); + MulAcc(4, 5); + MulAcc(5, 4); + MulAcc(6, 3); + MulAcc(7, 2); + + SaveMulAcc(9, 3, 7); + MulAcc(4, 6); + MulAcc(5, 5); + MulAcc(6, 4); + MulAcc(7, 3); + + SaveMulAcc(10, 4, 7); + MulAcc(5, 6); + MulAcc(6, 5); + MulAcc(7, 4); + + SaveMulAcc(11, 5, 7); + MulAcc(6, 6); + MulAcc(7, 5); + + SaveMulAcc(12, 6, 7); + MulAcc(7, 6); + + R[13] = c; + p = DWord::MultiplyAndAdd(A[7], B[7], d); + R[14] = p.GetLowHalf(); + R[15] = e + p.GetHighHalf(); +} + +void Portable::Multiply4Bottom(word *R, const word *A, const word *B) +{ + DWord p; + word c, d, e; + + p = DWord::Multiply(A[0], B[0]); + R[0] = p.GetLowHalf(); + c = p.GetHighHalf(); + d = e = 0; + + MulAcc(0, 1); + MulAcc(1, 0); + + SaveMulAcc(1, 2, 0); + MulAcc(1, 1); + MulAcc(0, 2); + + R[2] = c; + R[3] = d + A[0] * B[3] + A[1] * B[2] + A[2] * B[1] + A[3] * B[0]; +} + +void Portable::Multiply8Bottom(word *R, const word *A, const word *B) +{ + DWord p; + word c, d, e; + + p = DWord::Multiply(A[0], B[0]); + R[0] = p.GetLowHalf(); + c = p.GetHighHalf(); + d = e = 0; + + MulAcc(0, 1); + MulAcc(1, 0); + + SaveMulAcc(1, 2, 0); + MulAcc(1, 1); + MulAcc(0, 2); + + SaveMulAcc(2, 0, 3); + MulAcc(1, 2); + MulAcc(2, 1); + MulAcc(3, 0); + + SaveMulAcc(3, 0, 4); + MulAcc(1, 3); + MulAcc(2, 2); + MulAcc(3, 1); + MulAcc(4, 0); + + SaveMulAcc(4, 0, 5); + MulAcc(1, 4); + MulAcc(2, 3); + MulAcc(3, 2); + MulAcc(4, 1); + MulAcc(5, 0); + + SaveMulAcc(5, 0, 6); + MulAcc(1, 5); + MulAcc(2, 4); + MulAcc(3, 3); + MulAcc(4, 2); + MulAcc(5, 1); + MulAcc(6, 0); + + R[6] = c; + R[7] = d + A[0] * B[7] + A[1] * B[6] + A[2] * B[5] + A[3] * B[4] + + A[4] * B[3] + A[5] * B[2] + A[6] * B[1] + A[7] * B[0]; +} + + +#undef MulAcc +#undef SaveMulAcc +#undef SquAcc +#undef SaveSquAcc + +// optimized + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + +// ************** x86 feature detection *************** + + +#ifdef SSE2_INTRINSICS_AVAILABLE + +#ifndef _MSC_VER + static jmp_buf s_env; + static void SigIllHandler(int) + { + longjmp(s_env, 1); + } +#endif + +static bool HasSSE2() +{ + if (!IsPentium()) + return false; + + word32 cpuid[4]; + CpuId(1, cpuid); + if ((cpuid[3] & (1 << 26)) == 0) + return false; + +#ifdef _MSC_VER + __try + { + __asm xorpd xmm0, xmm0 // executing SSE2 instruction + } + __except (1) + { + return false; + } + return true; +#else + typedef void (*SigHandler)(int); + + SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + bool result = true; + if (setjmp(s_env)) + result = false; + else + __asm __volatile ("xorpd %xmm0, %xmm0"); + + signal(SIGILL, oldHandler); + return result; +#endif +} +#endif // SSE2_INTRINSICS_AVAILABLE + + +static bool IsP4() +{ + if (!IsPentium()) + return false; + + word32 cpuid[4]; + + CpuId(1, cpuid); + return ((cpuid[0] >> 8) & 0xf) == 0xf; +} + +// ************** Pentium/P4 optimizations *************** + +class PentiumOptimized : public Portable +{ +public: + static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B, + unsigned int N); + static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B, + unsigned int N); + static void TAOCRYPT_CDECL Multiply4(word *C, const word *A, + const word *B); + static void TAOCRYPT_CDECL Multiply8(word *C, const word *A, + const word *B); + static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A, + const word *B); +}; + +class P4Optimized +{ +public: + static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B, + unsigned int N); + static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B, + unsigned int N); +#ifdef SSE2_INTRINSICS_AVAILABLE + static void TAOCRYPT_CDECL Multiply4(word *C, const word *A, + const word *B); + static void TAOCRYPT_CDECL Multiply8(word *C, const word *A, + const word *B); + static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A, + const word *B); +#endif +}; + +typedef word (TAOCRYPT_CDECL * PAddSub)(word *C, const word *A, const word *B, + unsigned int N); +typedef void (TAOCRYPT_CDECL * PMul)(word *C, const word *A, const word *B); + +static PAddSub s_pAdd, s_pSub; +#ifdef SSE2_INTRINSICS_AVAILABLE +static PMul s_pMul4, s_pMul8, s_pMul8B; +#endif + +static void SetPentiumFunctionPointers() +{ + if (!IsPentium()) + { + s_pAdd = &Portable::Add; + s_pSub = &Portable::Subtract; + } + else if (IsP4()) + { + s_pAdd = &P4Optimized::Add; + s_pSub = &P4Optimized::Subtract; + } + else + { + s_pAdd = &PentiumOptimized::Add; + s_pSub = &PentiumOptimized::Subtract; + } + +#ifdef SSE2_INTRINSICS_AVAILABLE + if (!IsPentium()) + { + s_pMul4 = &Portable::Multiply4; + s_pMul8 = &Portable::Multiply8; + s_pMul8B = &Portable::Multiply8Bottom; + } + else if (HasSSE2()) + { + s_pMul4 = &P4Optimized::Multiply4; + s_pMul8 = &P4Optimized::Multiply8; + s_pMul8B = &P4Optimized::Multiply8Bottom; + } + else + { + s_pMul4 = &PentiumOptimized::Multiply4; + s_pMul8 = &PentiumOptimized::Multiply8; + s_pMul8B = &PentiumOptimized::Multiply8Bottom; + } +#endif +} + +static const char s_RunAtStartupSetPentiumFunctionPointers = + (SetPentiumFunctionPointers(), 0); + + +class LowLevel : public PentiumOptimized +{ +public: + inline static word Add(word *C, const word *A, const word *B, + unsigned int N) + {return s_pAdd(C, A, B, N);} + inline static word Subtract(word *C, const word *A, const word *B, + unsigned int N) + {return s_pSub(C, A, B, N);} + inline static void Square4(word *R, const word *A) + {Multiply4(R, A, A);} +#ifdef SSE2_INTRINSICS_AVAILABLE + inline static void Multiply4(word *C, const word *A, const word *B) + {s_pMul4(C, A, B);} + inline static void Multiply8(word *C, const word *A, const word *B) + {s_pMul8(C, A, B);} + inline static void Multiply8Bottom(word *C, const word *A, const word *B) + {s_pMul8B(C, A, B);} +#endif +}; + +// use some tricks to share assembly code between MSVC and GCC +#ifdef _MSC_VER + #define TAOCRYPT_NAKED __declspec(naked) + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + #define AddPrologue \ + __asm push ebp \ + __asm push ebx \ + __asm push esi \ + __asm push edi \ + __asm mov ecx, [esp+20] \ + __asm mov edx, [esp+24] \ + __asm mov ebx, [esp+28] \ + __asm mov esi, [esp+32] + #define AddEpilogue \ + __asm pop edi \ + __asm pop esi \ + __asm pop ebx \ + __asm pop ebp \ + __asm ret + #define MulPrologue \ + __asm push ebp \ + __asm push ebx \ + __asm push esi \ + __asm push edi \ + __asm mov ecx, [esp+28] \ + __asm mov esi, [esp+24] \ + __asm push [esp+20] + #define MulEpilogue \ + __asm add esp, 4 \ + __asm pop edi \ + __asm pop esi \ + __asm pop ebx \ + __asm pop ebp \ + __asm ret +#else + #define TAOCRYPT_NAKED + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + #define AddPrologue \ + word res; \ + __asm__ __volatile__ \ + ( \ + "push %%ebx;" /* save this manually, in case of -fPIC */ \ + "mov %3, %%ebx;" \ + ".intel_syntax noprefix;" \ + "push ebp;" + #define AddEpilogue \ + "pop ebp;" \ + ".att_syntax prefix;" \ + "pop %%ebx;" \ + "mov %%eax, %0;" \ + : "=g" (res) \ + : "c" (C), "d" (A), "m" (B), "S" (N) \ + : "%edi", "memory", "cc" \ + ); \ + return res; + + #define MulPrologue \ + __asm__ __volatile__ \ + ( \ + "push %%ebx;" /* save this manually, in case of -fPIC */ \ + "push %%ebp;" \ + "push %0;" \ + ".intel_syntax noprefix;" + #define MulEpilogue \ + "add esp, 4;" \ + "pop ebp;" \ + "pop ebx;" \ + ".att_syntax prefix;" \ + : \ + : "rm" (Z), "S" (X), "c" (Y) \ + : "%eax", "%edx", "%edi", "memory", "cc" \ + ); +#endif + +TAOCRYPT_NAKED word PentiumOptimized::Add(word *C, const word *A, + const word *B, unsigned int N) +{ + AddPrologue + + // now: ebx = B, ecx = C, edx = A, esi = N + AS2( sub ecx, edx) // hold the distance between C & A so we + // can add this to A to get C + AS2( xor eax, eax) // clear eax + + AS2( sub eax, esi) // eax is a negative index from end of B + AS2( lea ebx, [ebx+4*esi]) // ebx is end of B + + AS2( sar eax, 1) // unit of eax is now dwords; this also + // clears the carry flag + AS1( jz loopendAdd) // if no dwords then nothing to do + + AS1(loopstartAdd:) + AS2( mov esi,[edx]) // load lower word of A + AS2( mov ebp,[edx+4]) // load higher word of A + + AS2( mov edi,[ebx+8*eax]) // load lower word of B + AS2( lea edx,[edx+8]) // advance A and C + + AS2( adc esi,edi) // add lower words + AS2( mov edi,[ebx+8*eax+4]) // load higher word of B + + AS2( adc ebp,edi) // add higher words + AS1( inc eax) // advance B + + AS2( mov [edx+ecx-8],esi) // store lower word result + AS2( mov [edx+ecx-4],ebp) // store higher word result + + AS1( jnz loopstartAdd) // loop until eax overflows and becomes zero + + AS1(loopendAdd:) + AS2( adc eax, 0) // store carry into eax (return result register) + + AddEpilogue +} + +TAOCRYPT_NAKED word PentiumOptimized::Subtract(word *C, const word *A, + const word *B, unsigned int N) +{ + AddPrologue + + // now: ebx = B, ecx = C, edx = A, esi = N + AS2( sub ecx, edx) // hold the distance between C & A so we + // can add this to A to get C + AS2( xor eax, eax) // clear eax + + AS2( sub eax, esi) // eax is a negative index from end of B + AS2( lea ebx, [ebx+4*esi]) // ebx is end of B + + AS2( sar eax, 1) // unit of eax is now dwords; this also + // clears the carry flag + AS1( jz loopendSub) // if no dwords then nothing to do + + AS1(loopstartSub:) + AS2( mov esi,[edx]) // load lower word of A + AS2( mov ebp,[edx+4]) // load higher word of A + + AS2( mov edi,[ebx+8*eax]) // load lower word of B + AS2( lea edx,[edx+8]) // advance A and C + + AS2( sbb esi,edi) // subtract lower words + AS2( mov edi,[ebx+8*eax+4]) // load higher word of B + + AS2( sbb ebp,edi) // subtract higher words + AS1( inc eax) // advance B + + AS2( mov [edx+ecx-8],esi) // store lower word result + AS2( mov [edx+ecx-4],ebp) // store higher word result + + AS1( jnz loopstartSub) // loop until eax overflows and becomes zero + + AS1(loopendSub:) + AS2( adc eax, 0) // store carry into eax (return result register) + + AddEpilogue +} + +// On Pentium 4, the adc and sbb instructions are very expensive, so avoid them. + +TAOCRYPT_NAKED word P4Optimized::Add(word *C, const word *A, const word *B, + unsigned int N) +{ + AddPrologue + + // now: ebx = B, ecx = C, edx = A, esi = N + AS2( xor eax, eax) + AS1( neg esi) + AS1( jz loopendAddP4) // if no dwords then nothing to do + + AS2( mov edi, [edx]) + AS2( mov ebp, [ebx]) + AS1( jmp carry1AddP4) + + AS1(loopstartAddP4:) + AS2( mov edi, [edx+8]) + AS2( add ecx, 8) + AS2( add edx, 8) + AS2( mov ebp, [ebx]) + AS2( add edi, eax) + AS1( jc carry1AddP4) + AS2( xor eax, eax) + + AS1(carry1AddP4:) + AS2( add edi, ebp) + AS2( mov ebp, 1) + AS2( mov [ecx], edi) + AS2( mov edi, [edx+4]) + AS2( cmovc eax, ebp) + AS2( mov ebp, [ebx+4]) + AS2( add ebx, 8) + AS2( add edi, eax) + AS1( jc carry2AddP4) + AS2( xor eax, eax) + + AS1(carry2AddP4:) + AS2( add edi, ebp) + AS2( mov ebp, 1) + AS2( cmovc eax, ebp) + AS2( mov [ecx+4], edi) + AS2( add esi, 2) + AS1( jnz loopstartAddP4) + + AS1(loopendAddP4:) + + AddEpilogue +} + +TAOCRYPT_NAKED word P4Optimized::Subtract(word *C, const word *A, + const word *B, unsigned int N) +{ + AddPrologue + + // now: ebx = B, ecx = C, edx = A, esi = N + AS2( xor eax, eax) + AS1( neg esi) + AS1( jz loopendSubP4) // if no dwords then nothing to do + + AS2( mov edi, [edx]) + AS2( mov ebp, [ebx]) + AS1( jmp carry1SubP4) + + AS1(loopstartSubP4:) + AS2( mov edi, [edx+8]) + AS2( add edx, 8) + AS2( add ecx, 8) + AS2( mov ebp, [ebx]) + AS2( sub edi, eax) + AS1( jc carry1SubP4) + AS2( xor eax, eax) + + AS1(carry1SubP4:) + AS2( sub edi, ebp) + AS2( mov ebp, 1) + AS2( mov [ecx], edi) + AS2( mov edi, [edx+4]) + AS2( cmovc eax, ebp) + AS2( mov ebp, [ebx+4]) + AS2( add ebx, 8) + AS2( sub edi, eax) + AS1( jc carry2SubP4) + AS2( xor eax, eax) + + AS1(carry2SubP4:) + AS2( sub edi, ebp) + AS2( mov ebp, 1) + AS2( cmovc eax, ebp) + AS2( mov [ecx+4], edi) + AS2( add esi, 2) + AS1( jnz loopstartSubP4) + + AS1(loopendSubP4:) + + AddEpilogue +} + +// multiply assembly code originally contributed by Leonard Janke + +#define MulStartup \ + AS2(xor ebp, ebp) \ + AS2(xor edi, edi) \ + AS2(xor ebx, ebx) + +#define MulShiftCarry \ + AS2(mov ebp, edx) \ + AS2(mov edi, ebx) \ + AS2(xor ebx, ebx) + +#define MulAccumulateBottom(i,j) \ + AS2(mov eax, [ecx+4*j]) \ + AS2(imul eax, dword ptr [esi+4*i]) \ + AS2(add ebp, eax) + +#define MulAccumulate(i,j) \ + AS2(mov eax, [ecx+4*j]) \ + AS1(mul dword ptr [esi+4*i]) \ + AS2(add ebp, eax) \ + AS2(adc edi, edx) \ + AS2(adc bl, bh) + +#define MulStoreDigit(i) \ + AS2(mov edx, edi) \ + AS2(mov edi, [esp]) \ + AS2(mov [edi+4*i], ebp) + +#define MulLastDiagonal(digits) \ + AS2(mov eax, [ecx+4*(digits-1)]) \ + AS1(mul dword ptr [esi+4*(digits-1)]) \ + AS2(add ebp, eax) \ + AS2(adc edx, edi) \ + AS2(mov edi, [esp]) \ + AS2(mov [edi+4*(2*digits-2)], ebp) \ + AS2(mov [edi+4*(2*digits-1)], edx) + +TAOCRYPT_NAKED void PentiumOptimized::Multiply4(word* Z, const word* X, + const word* Y) +{ + MulPrologue + // now: [esp] = Z, esi = X, ecx = Y + MulStartup + MulAccumulate(0,0) + MulStoreDigit(0) + MulShiftCarry + + MulAccumulate(1,0) + MulAccumulate(0,1) + MulStoreDigit(1) + MulShiftCarry + + MulAccumulate(2,0) + MulAccumulate(1,1) + MulAccumulate(0,2) + MulStoreDigit(2) + MulShiftCarry + + MulAccumulate(3,0) + MulAccumulate(2,1) + MulAccumulate(1,2) + MulAccumulate(0,3) + MulStoreDigit(3) + MulShiftCarry + + MulAccumulate(3,1) + MulAccumulate(2,2) + MulAccumulate(1,3) + MulStoreDigit(4) + MulShiftCarry + + MulAccumulate(3,2) + MulAccumulate(2,3) + MulStoreDigit(5) + MulShiftCarry + + MulLastDiagonal(4) + MulEpilogue +} + +TAOCRYPT_NAKED void PentiumOptimized::Multiply8(word* Z, const word* X, + const word* Y) +{ + MulPrologue + // now: [esp] = Z, esi = X, ecx = Y + MulStartup + MulAccumulate(0,0) + MulStoreDigit(0) + MulShiftCarry + + MulAccumulate(1,0) + MulAccumulate(0,1) + MulStoreDigit(1) + MulShiftCarry + + MulAccumulate(2,0) + MulAccumulate(1,1) + MulAccumulate(0,2) + MulStoreDigit(2) + MulShiftCarry + + MulAccumulate(3,0) + MulAccumulate(2,1) + MulAccumulate(1,2) + MulAccumulate(0,3) + MulStoreDigit(3) + MulShiftCarry + + MulAccumulate(4,0) + MulAccumulate(3,1) + MulAccumulate(2,2) + MulAccumulate(1,3) + MulAccumulate(0,4) + MulStoreDigit(4) + MulShiftCarry + + MulAccumulate(5,0) + MulAccumulate(4,1) + MulAccumulate(3,2) + MulAccumulate(2,3) + MulAccumulate(1,4) + MulAccumulate(0,5) + MulStoreDigit(5) + MulShiftCarry + + MulAccumulate(6,0) + MulAccumulate(5,1) + MulAccumulate(4,2) + MulAccumulate(3,3) + MulAccumulate(2,4) + MulAccumulate(1,5) + MulAccumulate(0,6) + MulStoreDigit(6) + MulShiftCarry + + MulAccumulate(7,0) + MulAccumulate(6,1) + MulAccumulate(5,2) + MulAccumulate(4,3) + MulAccumulate(3,4) + MulAccumulate(2,5) + MulAccumulate(1,6) + MulAccumulate(0,7) + MulStoreDigit(7) + MulShiftCarry + + MulAccumulate(7,1) + MulAccumulate(6,2) + MulAccumulate(5,3) + MulAccumulate(4,4) + MulAccumulate(3,5) + MulAccumulate(2,6) + MulAccumulate(1,7) + MulStoreDigit(8) + MulShiftCarry + + MulAccumulate(7,2) + MulAccumulate(6,3) + MulAccumulate(5,4) + MulAccumulate(4,5) + MulAccumulate(3,6) + MulAccumulate(2,7) + MulStoreDigit(9) + MulShiftCarry + + MulAccumulate(7,3) + MulAccumulate(6,4) + MulAccumulate(5,5) + MulAccumulate(4,6) + MulAccumulate(3,7) + MulStoreDigit(10) + MulShiftCarry + + MulAccumulate(7,4) + MulAccumulate(6,5) + MulAccumulate(5,6) + MulAccumulate(4,7) + MulStoreDigit(11) + MulShiftCarry + + MulAccumulate(7,5) + MulAccumulate(6,6) + MulAccumulate(5,7) + MulStoreDigit(12) + MulShiftCarry + + MulAccumulate(7,6) + MulAccumulate(6,7) + MulStoreDigit(13) + MulShiftCarry + + MulLastDiagonal(8) + MulEpilogue +} + +TAOCRYPT_NAKED void PentiumOptimized::Multiply8Bottom(word* Z, const word* X, + const word* Y) +{ + MulPrologue + // now: [esp] = Z, esi = X, ecx = Y + MulStartup + MulAccumulate(0,0) + MulStoreDigit(0) + MulShiftCarry + + MulAccumulate(1,0) + MulAccumulate(0,1) + MulStoreDigit(1) + MulShiftCarry + + MulAccumulate(2,0) + MulAccumulate(1,1) + MulAccumulate(0,2) + MulStoreDigit(2) + MulShiftCarry + + MulAccumulate(3,0) + MulAccumulate(2,1) + MulAccumulate(1,2) + MulAccumulate(0,3) + MulStoreDigit(3) + MulShiftCarry + + MulAccumulate(4,0) + MulAccumulate(3,1) + MulAccumulate(2,2) + MulAccumulate(1,3) + MulAccumulate(0,4) + MulStoreDigit(4) + MulShiftCarry + + MulAccumulate(5,0) + MulAccumulate(4,1) + MulAccumulate(3,2) + MulAccumulate(2,3) + MulAccumulate(1,4) + MulAccumulate(0,5) + MulStoreDigit(5) + MulShiftCarry + + MulAccumulate(6,0) + MulAccumulate(5,1) + MulAccumulate(4,2) + MulAccumulate(3,3) + MulAccumulate(2,4) + MulAccumulate(1,5) + MulAccumulate(0,6) + MulStoreDigit(6) + MulShiftCarry + + MulAccumulateBottom(7,0) + MulAccumulateBottom(6,1) + MulAccumulateBottom(5,2) + MulAccumulateBottom(4,3) + MulAccumulateBottom(3,4) + MulAccumulateBottom(2,5) + MulAccumulateBottom(1,6) + MulAccumulateBottom(0,7) + MulStoreDigit(7) + MulEpilogue +} + +#undef AS1 +#undef AS2 + +#else // not x86 - no processor specific code at this layer + +typedef Portable LowLevel; + +#endif + +#ifdef SSE2_INTRINSICS_AVAILABLE + +#ifdef __GNUC__ +#define TAOCRYPT_FASTCALL +#else +#define TAOCRYPT_FASTCALL __fastcall +#endif + +static void TAOCRYPT_FASTCALL P4_Mul(__m128i *C, const __m128i *A, + const __m128i *B) +{ + __m128i a3210 = _mm_load_si128(A); + __m128i b3210 = _mm_load_si128(B); + + __m128i sum; + + __m128i z = _mm_setzero_si128(); + __m128i a2b2_a0b0 = _mm_mul_epu32(a3210, b3210); + C[0] = a2b2_a0b0; + + __m128i a3120 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(3, 1, 2, 0)); + __m128i b3021 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 2, 1)); + __m128i a1b0_a0b1 = _mm_mul_epu32(a3120, b3021); + __m128i a1b0 = _mm_unpackhi_epi32(a1b0_a0b1, z); + __m128i a0b1 = _mm_unpacklo_epi32(a1b0_a0b1, z); + C[1] = _mm_add_epi64(a1b0, a0b1); + + __m128i a31 = _mm_srli_epi64(a3210, 32); + __m128i b31 = _mm_srli_epi64(b3210, 32); + __m128i a3b3_a1b1 = _mm_mul_epu32(a31, b31); + C[6] = a3b3_a1b1; + + __m128i a1b1 = _mm_unpacklo_epi32(a3b3_a1b1, z); + __m128i b3012 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 1, 2)); + __m128i a2b0_a0b2 = _mm_mul_epu32(a3210, b3012); + __m128i a0b2 = _mm_unpacklo_epi32(a2b0_a0b2, z); + __m128i a2b0 = _mm_unpackhi_epi32(a2b0_a0b2, z); + sum = _mm_add_epi64(a1b1, a0b2); + C[2] = _mm_add_epi64(sum, a2b0); + + __m128i a2301 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(2, 3, 0, 1)); + __m128i b2103 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(2, 1, 0, 3)); + __m128i a3b0_a1b2 = _mm_mul_epu32(a2301, b3012); + __m128i a2b1_a0b3 = _mm_mul_epu32(a3210, b2103); + __m128i a3b0 = _mm_unpackhi_epi32(a3b0_a1b2, z); + __m128i a1b2 = _mm_unpacklo_epi32(a3b0_a1b2, z); + __m128i a2b1 = _mm_unpackhi_epi32(a2b1_a0b3, z); + __m128i a0b3 = _mm_unpacklo_epi32(a2b1_a0b3, z); + __m128i sum1 = _mm_add_epi64(a3b0, a1b2); + sum = _mm_add_epi64(a2b1, a0b3); + C[3] = _mm_add_epi64(sum, sum1); + + __m128i a3b1_a1b3 = _mm_mul_epu32(a2301, b2103); + __m128i a2b2 = _mm_unpackhi_epi32(a2b2_a0b0, z); + __m128i a3b1 = _mm_unpackhi_epi32(a3b1_a1b3, z); + __m128i a1b3 = _mm_unpacklo_epi32(a3b1_a1b3, z); + sum = _mm_add_epi64(a2b2, a3b1); + C[4] = _mm_add_epi64(sum, a1b3); + + __m128i a1302 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(1, 3, 0, 2)); + __m128i b1203 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(1, 2, 0, 3)); + __m128i a3b2_a2b3 = _mm_mul_epu32(a1302, b1203); + __m128i a3b2 = _mm_unpackhi_epi32(a3b2_a2b3, z); + __m128i a2b3 = _mm_unpacklo_epi32(a3b2_a2b3, z); + C[5] = _mm_add_epi64(a3b2, a2b3); +} + +void P4Optimized::Multiply4(word *C, const word *A, const word *B) +{ + __m128i temp[7]; + const word *w = (word *)temp; + const __m64 *mw = (__m64 *)w; + + P4_Mul(temp, (__m128i *)A, (__m128i *)B); + + C[0] = w[0]; + + __m64 s1, s2; + + __m64 w1 = _mm_cvtsi32_si64(w[1]); + __m64 w4 = mw[2]; + __m64 w6 = mw[3]; + __m64 w8 = mw[4]; + __m64 w10 = mw[5]; + __m64 w12 = mw[6]; + __m64 w14 = mw[7]; + __m64 w16 = mw[8]; + __m64 w18 = mw[9]; + __m64 w20 = mw[10]; + __m64 w22 = mw[11]; + __m64 w26 = _mm_cvtsi32_si64(w[26]); + + s1 = _mm_add_si64(w1, w4); + C[1] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w6, w8); + s1 = _mm_add_si64(s1, s2); + C[2] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w10, w12); + s1 = _mm_add_si64(s1, s2); + C[3] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w14, w16); + s1 = _mm_add_si64(s1, s2); + C[4] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w18, w20); + s1 = _mm_add_si64(s1, s2); + C[5] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w22, w26); + s1 = _mm_add_si64(s1, s2); + C[6] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + C[7] = _mm_cvtsi64_si32(s1) + w[27]; + _mm_empty(); +} + +void P4Optimized::Multiply8(word *C, const word *A, const word *B) +{ + __m128i temp[28]; + const word *w = (word *)temp; + const __m64 *mw = (__m64 *)w; + const word *x = (word *)temp+7*4; + const __m64 *mx = (__m64 *)x; + const word *y = (word *)temp+7*4*2; + const __m64 *my = (__m64 *)y; + const word *z = (word *)temp+7*4*3; + const __m64 *mz = (__m64 *)z; + + P4_Mul(temp, (__m128i *)A, (__m128i *)B); + + P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B); + + P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1); + + P4_Mul(temp+21, (__m128i *)A+1, (__m128i *)B+1); + + C[0] = w[0]; + + __m64 s1, s2, s3, s4; + + __m64 w1 = _mm_cvtsi32_si64(w[1]); + __m64 w4 = mw[2]; + __m64 w6 = mw[3]; + __m64 w8 = mw[4]; + __m64 w10 = mw[5]; + __m64 w12 = mw[6]; + __m64 w14 = mw[7]; + __m64 w16 = mw[8]; + __m64 w18 = mw[9]; + __m64 w20 = mw[10]; + __m64 w22 = mw[11]; + __m64 w26 = _mm_cvtsi32_si64(w[26]); + __m64 w27 = _mm_cvtsi32_si64(w[27]); + + __m64 x0 = _mm_cvtsi32_si64(x[0]); + __m64 x1 = _mm_cvtsi32_si64(x[1]); + __m64 x4 = mx[2]; + __m64 x6 = mx[3]; + __m64 x8 = mx[4]; + __m64 x10 = mx[5]; + __m64 x12 = mx[6]; + __m64 x14 = mx[7]; + __m64 x16 = mx[8]; + __m64 x18 = mx[9]; + __m64 x20 = mx[10]; + __m64 x22 = mx[11]; + __m64 x26 = _mm_cvtsi32_si64(x[26]); + __m64 x27 = _mm_cvtsi32_si64(x[27]); + + __m64 y0 = _mm_cvtsi32_si64(y[0]); + __m64 y1 = _mm_cvtsi32_si64(y[1]); + __m64 y4 = my[2]; + __m64 y6 = my[3]; + __m64 y8 = my[4]; + __m64 y10 = my[5]; + __m64 y12 = my[6]; + __m64 y14 = my[7]; + __m64 y16 = my[8]; + __m64 y18 = my[9]; + __m64 y20 = my[10]; + __m64 y22 = my[11]; + __m64 y26 = _mm_cvtsi32_si64(y[26]); + __m64 y27 = _mm_cvtsi32_si64(y[27]); + + __m64 z0 = _mm_cvtsi32_si64(z[0]); + __m64 z1 = _mm_cvtsi32_si64(z[1]); + __m64 z4 = mz[2]; + __m64 z6 = mz[3]; + __m64 z8 = mz[4]; + __m64 z10 = mz[5]; + __m64 z12 = mz[6]; + __m64 z14 = mz[7]; + __m64 z16 = mz[8]; + __m64 z18 = mz[9]; + __m64 z20 = mz[10]; + __m64 z22 = mz[11]; + __m64 z26 = _mm_cvtsi32_si64(z[26]); + + s1 = _mm_add_si64(w1, w4); + C[1] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w6, w8); + s1 = _mm_add_si64(s1, s2); + C[2] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w10, w12); + s1 = _mm_add_si64(s1, s2); + C[3] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x0, y0); + s2 = _mm_add_si64(w14, w16); + s1 = _mm_add_si64(s1, s3); + s1 = _mm_add_si64(s1, s2); + C[4] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x1, y1); + s4 = _mm_add_si64(x4, y4); + s1 = _mm_add_si64(s1, w18); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, w20); + s1 = _mm_add_si64(s1, s3); + C[5] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x6, y6); + s4 = _mm_add_si64(x8, y8); + s1 = _mm_add_si64(s1, w22); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, w26); + s1 = _mm_add_si64(s1, s3); + C[6] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x10, y10); + s4 = _mm_add_si64(x12, y12); + s1 = _mm_add_si64(s1, w27); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, s3); + C[7] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x14, y14); + s4 = _mm_add_si64(x16, y16); + s1 = _mm_add_si64(s1, z0); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, s3); + C[8] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x18, y18); + s4 = _mm_add_si64(x20, y20); + s1 = _mm_add_si64(s1, z1); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, z4); + s1 = _mm_add_si64(s1, s3); + C[9] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x22, y22); + s4 = _mm_add_si64(x26, y26); + s1 = _mm_add_si64(s1, z6); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, z8); + s1 = _mm_add_si64(s1, s3); + C[10] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x27, y27); + s1 = _mm_add_si64(s1, z10); + s1 = _mm_add_si64(s1, z12); + s1 = _mm_add_si64(s1, s3); + C[11] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(z14, z16); + s1 = _mm_add_si64(s1, s3); + C[12] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(z18, z20); + s1 = _mm_add_si64(s1, s3); + C[13] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(z22, z26); + s1 = _mm_add_si64(s1, s3); + C[14] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + C[15] = z[27] + _mm_cvtsi64_si32(s1); + _mm_empty(); +} + +void P4Optimized::Multiply8Bottom(word *C, const word *A, const word *B) +{ + __m128i temp[21]; + const word *w = (word *)temp; + const __m64 *mw = (__m64 *)w; + const word *x = (word *)temp+7*4; + const __m64 *mx = (__m64 *)x; + const word *y = (word *)temp+7*4*2; + const __m64 *my = (__m64 *)y; + + P4_Mul(temp, (__m128i *)A, (__m128i *)B); + + P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B); + + P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1); + + C[0] = w[0]; + + __m64 s1, s2, s3, s4; + + __m64 w1 = _mm_cvtsi32_si64(w[1]); + __m64 w4 = mw[2]; + __m64 w6 = mw[3]; + __m64 w8 = mw[4]; + __m64 w10 = mw[5]; + __m64 w12 = mw[6]; + __m64 w14 = mw[7]; + __m64 w16 = mw[8]; + __m64 w18 = mw[9]; + __m64 w20 = mw[10]; + __m64 w22 = mw[11]; + __m64 w26 = _mm_cvtsi32_si64(w[26]); + + __m64 x0 = _mm_cvtsi32_si64(x[0]); + __m64 x1 = _mm_cvtsi32_si64(x[1]); + __m64 x4 = mx[2]; + __m64 x6 = mx[3]; + __m64 x8 = mx[4]; + + __m64 y0 = _mm_cvtsi32_si64(y[0]); + __m64 y1 = _mm_cvtsi32_si64(y[1]); + __m64 y4 = my[2]; + __m64 y6 = my[3]; + __m64 y8 = my[4]; + + s1 = _mm_add_si64(w1, w4); + C[1] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w6, w8); + s1 = _mm_add_si64(s1, s2); + C[2] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s2 = _mm_add_si64(w10, w12); + s1 = _mm_add_si64(s1, s2); + C[3] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x0, y0); + s2 = _mm_add_si64(w14, w16); + s1 = _mm_add_si64(s1, s3); + s1 = _mm_add_si64(s1, s2); + C[4] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x1, y1); + s4 = _mm_add_si64(x4, y4); + s1 = _mm_add_si64(s1, w18); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, w20); + s1 = _mm_add_si64(s1, s3); + C[5] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + s3 = _mm_add_si64(x6, y6); + s4 = _mm_add_si64(x8, y8); + s1 = _mm_add_si64(s1, w22); + s3 = _mm_add_si64(s3, s4); + s1 = _mm_add_si64(s1, w26); + s1 = _mm_add_si64(s1, s3); + C[6] = _mm_cvtsi64_si32(s1); + s1 = _mm_srli_si64(s1, 32); + + C[7] = _mm_cvtsi64_si32(s1) + w[27] + x[10] + y[10] + x[12] + y[12]; + _mm_empty(); +} + +#endif // #ifdef SSE2_INTRINSICS_AVAILABLE + +// end optimized + +// ******************************************************** + +#define A0 A +#define A1 (A+N2) +#define B0 B +#define B1 (B+N2) + +#define T0 T +#define T1 (T+N2) +#define T2 (T+N) +#define T3 (T+N+N2) + +#define R0 R +#define R1 (R+N2) +#define R2 (R+N) +#define R3 (R+N+N2) + +//VC60 workaround: compiler bug triggered without the extra dummy parameters + +// R[2*N] - result = A*B +// T[2*N] - temporary work space +// A[N] --- multiplier +// B[N] --- multiplicant + + +void RecursiveMultiply(word *R, word *T, const word *A, const word *B, + unsigned int N) +{ + if (LowLevel::MultiplyRecursionLimit() >= 8 && N==8) + LowLevel::Multiply8(R, A, B); + else if (LowLevel::MultiplyRecursionLimit() >= 4 && N==4) + LowLevel::Multiply4(R, A, B); + else if (N==2) + LowLevel::Multiply2(R, A, B); + else + { + const unsigned int N2 = N/2; + int carry; + + int aComp = Compare(A0, A1, N2); + int bComp = Compare(B0, B1, N2); + + switch (2*aComp + aComp + bComp) + { + case -4: + LowLevel::Subtract(R0, A1, A0, N2); + LowLevel::Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + LowLevel::Subtract(T1, T1, R0, N2); + carry = -1; + break; + case -2: + LowLevel::Subtract(R0, A1, A0, N2); + LowLevel::Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 2: + LowLevel::Subtract(R0, A0, A1, N2); + LowLevel::Subtract(R1, B1, B0, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 4: + LowLevel::Subtract(R0, A1, A0, N2); + LowLevel::Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + LowLevel::Subtract(T1, T1, R1, N2); + carry = -1; + break; + default: + SetWords(T0, 0, N); + carry = 0; + } + + RecursiveMultiply(R0, T2, A0, B0, N2); + RecursiveMultiply(R2, T2, A1, B1, N2); + + // now T[01] holds (A1-A0)*(B0-B1),R[01] holds A0*B0, R[23] holds A1*B1 + + carry += LowLevel::Add(T0, T0, R0, N); + carry += LowLevel::Add(T0, T0, R2, N); + carry += LowLevel::Add(R1, R1, T0, N); + + Increment(R3, N2, carry); + } +} + + +void RecursiveSquare(word *R, word *T, const word *A, unsigned int N) +{ + if (LowLevel::SquareRecursionLimit() >= 4 && N==4) + LowLevel::Square4(R, A); + else if (N==2) + LowLevel::Square2(R, A); + else + { + const unsigned int N2 = N/2; + + RecursiveSquare(R0, T2, A0, N2); + RecursiveSquare(R2, T2, A1, N2); + RecursiveMultiply(T0, T2, A0, A1, N2); + + word carry = LowLevel::Add(R1, R1, T0, N); + carry += LowLevel::Add(R1, R1, T0, N); + Increment(R3, N2, carry); + } +} + + +// R[N] - bottom half of A*B +// T[N] - temporary work space +// A[N] - multiplier +// B[N] - multiplicant + + +void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, + unsigned int N) +{ + if (LowLevel::MultiplyBottomRecursionLimit() >= 8 && N==8) + LowLevel::Multiply8Bottom(R, A, B); + else if (LowLevel::MultiplyBottomRecursionLimit() >= 4 && N==4) + LowLevel::Multiply4Bottom(R, A, B); + else if (N==2) + LowLevel::Multiply2Bottom(R, A, B); + else + { + const unsigned int N2 = N/2; + + RecursiveMultiply(R, T, A0, B0, N2); + RecursiveMultiplyBottom(T0, T1, A1, B0, N2); + LowLevel::Add(R1, R1, T0, N2); + RecursiveMultiplyBottom(T0, T1, A0, B1, N2); + LowLevel::Add(R1, R1, T0, N2); + } +} + + +void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A, + const word *B, unsigned int N) +{ + if (N==4) + { + LowLevel::Multiply4(T, A, B); + memcpy(R, T+4, 4*WORD_SIZE); + } + else if (N==2) + { + LowLevel::Multiply2(T, A, B); + memcpy(R, T+2, 2*WORD_SIZE); + } + else + { + const unsigned int N2 = N/2; + int carry; + + int aComp = Compare(A0, A1, N2); + int bComp = Compare(B0, B1, N2); + + switch (2*aComp + aComp + bComp) + { + case -4: + LowLevel::Subtract(R0, A1, A0, N2); + LowLevel::Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + LowLevel::Subtract(T1, T1, R0, N2); + carry = -1; + break; + case -2: + LowLevel::Subtract(R0, A1, A0, N2); + LowLevel::Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 2: + LowLevel::Subtract(R0, A0, A1, N2); + LowLevel::Subtract(R1, B1, B0, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + carry = 0; + break; + case 4: + LowLevel::Subtract(R0, A1, A0, N2); + LowLevel::Subtract(R1, B0, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + LowLevel::Subtract(T1, T1, R1, N2); + carry = -1; + break; + default: + SetWords(T0, 0, N); + carry = 0; + } + + RecursiveMultiply(T2, R0, A1, B1, N2); + + // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1 + + word c2 = LowLevel::Subtract(R0, L+N2, L, N2); + c2 += LowLevel::Subtract(R0, R0, T0, N2); + word t = (Compare(R0, T2, N2) == -1); + + carry += t; + carry += Increment(R0, N2, c2+t); + carry += LowLevel::Add(R0, R0, T1, N2); + carry += LowLevel::Add(R0, R0, T3, N2); + + CopyWords(R1, T3, N2); + Increment(R1, N2, carry); + } +} + + +inline word Add(word *C, const word *A, const word *B, unsigned int N) +{ + return LowLevel::Add(C, A, B, N); +} + +inline word Subtract(word *C, const word *A, const word *B, unsigned int N) +{ + return LowLevel::Subtract(C, A, B, N); +} + +inline void Multiply(word *R, word *T, const word *A, const word *B, + unsigned int N) +{ + RecursiveMultiply(R, T, A, B, N); +} + +inline void Square(word *R, word *T, const word *A, unsigned int N) +{ + RecursiveSquare(R, T, A, N); +} + + +void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA, + const word *B, unsigned int NB) +{ + if (NA == NB) + { + if (A == B) + Square(R, T, A, NA); + else + Multiply(R, T, A, B, NA); + + return; + } + + if (NA > NB) + { + STL::swap(A, B); + STL::swap(NA, NB); + } + + if (NA==2 && !A[1]) + { + switch (A[0]) + { + case 0: + SetWords(R, 0, NB+2); + return; + case 1: + CopyWords(R, B, NB); + R[NB] = R[NB+1] = 0; + return; + default: + R[NB] = LinearMultiply(R, B, A[0], NB); + R[NB+1] = 0; + return; + } + } + + Multiply(R, T, A, B, NA); + CopyWords(T+2*NA, R+NA, NA); + + unsigned i; + + for (i=2*NA; i>=1; + i++; + } + k+=i; + + if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2) + { + if (s%2==0) + CopyWords(R, b, N); + else + Subtract(R, M, b, N); + return k; + } + + ShiftWordsRightByBits(f, fgLen, i); + t=ShiftWordsLeftByBits(c, bcLen, i); + if (t) + { + c[bcLen] = t; + bcLen+=2; + } + + if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0) + fgLen-=2; + + if (Compare(f, g, fgLen)==-1) + { + STL::swap(f, g); + STL::swap(b, c); + s++; + } + + Subtract(f, f, g, fgLen); + + if (Add(b, b, c, bcLen)) + { + b[bcLen] = 1; + bcLen+=2; + } + } +} + +// R[N] - result = A/(2^k) mod M +// A[N] - input +// M[N] - modulus + +void DivideByPower2Mod(word *R, const word *A, unsigned int k, const word *M, + unsigned int N) +{ + CopyWords(R, A, N); + + while (k--) + { + if (R[0]%2==0) + ShiftWordsRightByBits(R, N, 1); + else + { + word carry = Add(R, R, M, N); + ShiftWordsRightByBits(R, N, 1); + R[N-1] += carry<<(WORD_BITS-1); + } + } +} + +// R[N] - result = A*(2^k) mod M +// A[N] - input +// M[N] - modulus + +void MultiplyByPower2Mod(word *R, const word *A, unsigned int k, const word *M, + unsigned int N) +{ + CopyWords(R, A, N); + + while (k--) + if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0) + Subtract(R, R, M, N); +} + + +// ********** end of integer needs + + +Integer::Integer() + : reg_(2), sign_(POSITIVE) +{ + reg_[0] = reg_[1] = 0; +} + + +Integer::Integer(const Integer& t) + : reg_(RoundupSize(t.WordCount())), sign_(t.sign_) +{ + CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size()); +} + + +Integer::Integer(signed long value) + : reg_(2) +{ + if (value >= 0) + sign_ = POSITIVE; + else + { + sign_ = NEGATIVE; + value = -value; + } + reg_[0] = word(value); + reg_[1] = word(SafeRightShift(value)); +} + + +Integer::Integer(Sign s, word high, word low) + : reg_(2), sign_(s) +{ + reg_[0] = low; + reg_[1] = high; +} + + +Integer::Integer(word value, unsigned int length) + : reg_(RoundupSize(length)), sign_(POSITIVE) +{ + reg_[0] = value; + SetWords(reg_ + 1, 0, reg_.size() - 1); +} + + +Integer::Integer(const byte *encodedInteger, unsigned int byteCount, + Signedness s) +{ + Decode(encodedInteger, byteCount, s); +} + +class BadBER {}; + +// BER Decode Source +Integer::Integer(Source& source) + : reg_(2), sign_(POSITIVE) +{ + Decode(source); +} + +void Integer::Decode(Source& source) +{ + byte b = source.next(); + if (b != INTEGER) { + source.SetError(INTEGER_E); + return; + } + + word32 length = GetLength(source); + if (length == 0 || source.GetError().What()) return; + + if ( (b = source.next()) == 0x00) + length--; + else + source.prev(); + + if (source.IsLeft(length) == false) return; + + unsigned int words = (length + WORD_SIZE - 1) / WORD_SIZE; + words = RoundupSize(words); + if (words > reg_.size()) reg_.CleanNew(words); + + for (int j = length; j > 0; j--) { + b = source.next(); + reg_ [(j-1) / WORD_SIZE] |= (word)b << ((j-1) % WORD_SIZE) * 8; + } +} + + +void Integer::Decode(const byte* input, unsigned int inputLen, Signedness s) +{ + unsigned int idx(0); + byte b = 0; + if (inputLen>0) + b = input[idx]; // peek + sign_ = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE; + + while (inputLen>0 && (sign_==POSITIVE ? b==0 : b==0xff)) + { + idx++; // skip + if (--inputLen>0) + b = input[idx]; // peek + } + + reg_.CleanNew(RoundupSize(BytesToWords(inputLen))); + + for (unsigned int i=inputLen; i > 0; i--) + { + b = input[idx++]; + reg_[(i-1)/WORD_SIZE] |= (word)b << ((i-1)%WORD_SIZE)*8; + } + + if (sign_ == NEGATIVE) + { + for (unsigned i=inputLen; i 0; i--) + output[idx++] = GetByte(i-1); + } + else + { + // take two's complement of *this + Integer temp = Integer::Power2(8*max(ByteCount(), outputLen)) + *this; + for (unsigned i=0; i range); + + *this += min; +} + + +Integer Integer::Power2(unsigned int e) +{ + Integer r((word)0, BitsToWords(e + 1)); + r.SetBit(e); + return r; +} + + +void Integer::SetBit(unsigned int n, bool value) +{ + if (value) + { + reg_.CleanGrow(RoundupSize(BitsToWords(n + 1))); + reg_[n / WORD_BITS] |= (word(1) << (n % WORD_BITS)); + } + else + { + if (n / WORD_BITS < reg_.size()) + reg_[n / WORD_BITS] &= ~(word(1) << (n % WORD_BITS)); + } +} + + +void Integer::SetByte(unsigned int n, byte value) +{ + reg_.CleanGrow(RoundupSize(BytesToWords(n+1))); + reg_[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); + reg_[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); +} + + +void Integer::Negate() +{ + if (!!(*this)) // don't flip sign if *this==0 + sign_ = Sign(1 - sign_); +} + + +bool Integer::operator!() const +{ + return IsNegative() ? false : (reg_[0]==0 && WordCount()==0); +} + + +Integer& Integer::operator=(const Integer& t) +{ + if (this != &t) + { + reg_.New(RoundupSize(t.WordCount())); + CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size()); + sign_ = t.sign_; + } + return *this; +} + + +Integer& Integer::operator+=(const Integer& t) +{ + reg_.CleanGrow(t.reg_.size()); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveAdd(*this, *this, t); + else + PositiveSubtract(*this, *this, t); + } + else + { + if (t.NotNegative()) + PositiveSubtract(*this, t, *this); + else + { + PositiveAdd(*this, *this, t); + sign_ = Integer::NEGATIVE; + } + } + return *this; +} + + +Integer Integer::operator-() const +{ + Integer result(*this); + result.Negate(); + return result; +} + + +Integer& Integer::operator-=(const Integer& t) +{ + reg_.CleanGrow(t.reg_.size()); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveSubtract(*this, *this, t); + else + PositiveAdd(*this, *this, t); + } + else + { + if (t.NotNegative()) + { + PositiveAdd(*this, *this, t); + sign_ = Integer::NEGATIVE; + } + else + PositiveSubtract(*this, t, *this); + } + return *this; +} + + +Integer& Integer::operator++() +{ + if (NotNegative()) + { + if (Increment(reg_.get_buffer(), reg_.size())) + { + reg_.CleanGrow(2*reg_.size()); + reg_[reg_.size()/2]=1; + } + } + else + { + word borrow = Decrement(reg_.get_buffer(), reg_.size()); + (void)borrow; // shut up compiler + if (WordCount()==0) + *this = Zero(); + } + return *this; +} + +Integer& Integer::operator--() +{ + if (IsNegative()) + { + if (Increment(reg_.get_buffer(), reg_.size())) + { + reg_.CleanGrow(2*reg_.size()); + reg_[reg_.size()/2]=1; + } + } + else + { + if (Decrement(reg_.get_buffer(), reg_.size())) + *this = -One(); + } + return *this; +} + + +Integer& Integer::operator<<=(unsigned int n) +{ + const unsigned int wordCount = WordCount(); + const unsigned int shiftWords = n / WORD_BITS; + const unsigned int shiftBits = n % WORD_BITS; + + reg_.CleanGrow(RoundupSize(wordCount+BitsToWords(n))); + ShiftWordsLeftByWords(reg_.get_buffer(), wordCount + shiftWords, + shiftWords); + ShiftWordsLeftByBits(reg_+shiftWords, wordCount+BitsToWords(shiftBits), + shiftBits); + return *this; +} + +Integer& Integer::operator>>=(unsigned int n) +{ + const unsigned int wordCount = WordCount(); + const unsigned int shiftWords = n / WORD_BITS; + const unsigned int shiftBits = n % WORD_BITS; + + ShiftWordsRightByWords(reg_.get_buffer(), wordCount, shiftWords); + if (wordCount > shiftWords) + ShiftWordsRightByBits(reg_.get_buffer(), wordCount-shiftWords, + shiftBits); + if (IsNegative() && WordCount()==0) // avoid -0 + *this = Zero(); + return *this; +} + + +void PositiveAdd(Integer& sum, const Integer& a, const Integer& b) +{ + word carry; + if (a.reg_.size() == b.reg_.size()) + carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), a.reg_.size()); + else if (a.reg_.size() > b.reg_.size()) + { + carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), b.reg_.size()); + CopyWords(sum.reg_+b.reg_.size(), a.reg_+b.reg_.size(), + a.reg_.size()-b.reg_.size()); + carry = Increment(sum.reg_+b.reg_.size(), a.reg_.size()-b.reg_.size(), + carry); + } + else + { + carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), a.reg_.size()); + CopyWords(sum.reg_+a.reg_.size(), b.reg_+a.reg_.size(), + b.reg_.size()-a.reg_.size()); + carry = Increment(sum.reg_+a.reg_.size(), b.reg_.size()-a.reg_.size(), + carry); + } + + if (carry) + { + sum.reg_.CleanGrow(2*sum.reg_.size()); + sum.reg_[sum.reg_.size()/2] = 1; + } + sum.sign_ = Integer::POSITIVE; +} + +void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) +{ + unsigned aSize = a.WordCount(); + aSize += aSize%2; + unsigned bSize = b.WordCount(); + bSize += bSize%2; + + if (aSize == bSize) + { + if (Compare(a.reg_.get_buffer(), b.reg_.get_buffer(), aSize) >= 0) + { + Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), aSize); + diff.sign_ = Integer::POSITIVE; + } + else + { + Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(), + a.reg_.get_buffer(), aSize); + diff.sign_ = Integer::NEGATIVE; + } + } + else if (aSize > bSize) + { + word borrow = Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), bSize); + CopyWords(diff.reg_+bSize, a.reg_+bSize, aSize-bSize); + borrow = Decrement(diff.reg_+bSize, aSize-bSize, borrow); + diff.sign_ = Integer::POSITIVE; + } + else + { + word borrow = Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(), + a.reg_.get_buffer(), aSize); + CopyWords(diff.reg_+aSize, b.reg_+aSize, bSize-aSize); + borrow = Decrement(diff.reg_+aSize, bSize-aSize, borrow); + diff.sign_ = Integer::NEGATIVE; + } +} + + +unsigned int Integer::MinEncodedSize(Signedness signedness) const +{ + unsigned int outputLen = max(1U, ByteCount()); + if (signedness == UNSIGNED) + return outputLen; + if (NotNegative() && (GetByte(outputLen-1) & 0x80)) + outputLen++; + if (IsNegative() && *this < -Power2(outputLen*8-1)) + outputLen++; + return outputLen; +} + + +int Integer::Compare(const Integer& t) const +{ + if (NotNegative()) + { + if (t.NotNegative()) + return PositiveCompare(t); + else + return 1; + } + else + { + if (t.NotNegative()) + return -1; + else + return -PositiveCompare(t); + } +} + + +int Integer::PositiveCompare(const Integer& t) const +{ + unsigned size = WordCount(), tSize = t.WordCount(); + + if (size == tSize) + return TaoCrypt::Compare(reg_.get_buffer(), t.reg_.get_buffer(), size); + else + return size > tSize ? 1 : -1; +} + + +bool Integer::GetBit(unsigned int n) const +{ + if (n/WORD_BITS >= reg_.size()) + return 0; + else + return bool((reg_[n/WORD_BITS] >> (n % WORD_BITS)) & 1); +} + + +unsigned long Integer::GetBits(unsigned int i, unsigned int n) const +{ + unsigned long v = 0; + for (unsigned int j=0; j= reg_.size()) + return 0; + else + return byte(reg_[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); +} + + +unsigned int Integer::BitCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_BITS + BitPrecision(reg_[wordCount-1]); + else + return 0; +} + + +unsigned int Integer::ByteCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_SIZE + BytePrecision(reg_[wordCount-1]); + else + return 0; +} + + +unsigned int Integer::WordCount() const +{ + return CountWords(reg_.get_buffer(), reg_.size()); +} + + +bool Integer::IsConvertableToLong() const +{ + if (ByteCount() > sizeof(long)) + return false; + + unsigned long value = reg_[0]; + value += SafeLeftShift(reg_[1]); + + if (sign_ == POSITIVE) + return (signed long)value >= 0; + else + return -(signed long)value < 0; +} + + +signed long Integer::ConvertToLong() const +{ + unsigned long value = reg_[0]; + value += SafeLeftShift(reg_[1]); + return sign_ == POSITIVE ? value : -(signed long)value; +} + + +void Integer::Swap(Integer& a) +{ + reg_.Swap(a.reg_); + STL::swap(sign_, a.sign_); +} + + +Integer Integer::Plus(const Integer& b) const +{ + Integer sum((word)0, max(reg_.size(), b.reg_.size())); + if (NotNegative()) + { + if (b.NotNegative()) + PositiveAdd(sum, *this, b); + else + PositiveSubtract(sum, *this, b); + } + else + { + if (b.NotNegative()) + PositiveSubtract(sum, b, *this); + else + { + PositiveAdd(sum, *this, b); + sum.sign_ = Integer::NEGATIVE; + } + } + return sum; +} + + +Integer Integer::Minus(const Integer& b) const +{ + Integer diff((word)0, max(reg_.size(), b.reg_.size())); + if (NotNegative()) + { + if (b.NotNegative()) + PositiveSubtract(diff, *this, b); + else + PositiveAdd(diff, *this, b); + } + else + { + if (b.NotNegative()) + { + PositiveAdd(diff, *this, b); + diff.sign_ = Integer::NEGATIVE; + } + else + PositiveSubtract(diff, b, *this); + } + return diff; +} + + +Integer Integer::Times(const Integer &b) const +{ + Integer product; + Multiply(product, *this, b); + return product; +} + + +#undef A0 +#undef A1 +#undef B0 +#undef B1 + +#undef T0 +#undef T1 +#undef T2 +#undef T3 + +#undef R0 +#undef R1 +#undef R2 +#undef R3 + + +static inline void AtomicDivide(word *Q, const word *A, const word *B) +{ + word T[4]; + DWord q = DivideFourWordsByTwo(T, DWord(A[0], A[1]), + DWord(A[2], A[3]), DWord(B[0], B[1])); + Q[0] = q.GetLowHalf(); + Q[1] = q.GetHighHalf(); + +#ifndef NDEBUG + if (B[0] || B[1]) + { + // multiply quotient and divisor and add remainder, make sure it + // equals dividend + word P[4]; + Portable::Multiply2(P, Q, B); + Add(P, P, T, 4); + } +#endif +} + + +// for use by Divide(), corrects the underestimated quotient {Q1,Q0} +static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B, + unsigned int N) +{ + if (Q[1]) + { + T[N] = T[N+1] = 0; + unsigned i; + for (i=0; i= 0) + { + R[N] -= Subtract(R, R, B, N); + Q[1] += (++Q[0]==0); + } +} + +// R[NB] -------- remainder = A%B +// Q[NA-NB+2] --- quotient = A/B +// T[NA+2*NB+4] - temp work space +// A[NA] -------- dividend +// B[NB] -------- divisor + + +void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA, + const word* B, unsigned int NB) +{ + // set up temporary work space + word *const TA=T; + word *const TB=T+NA+2; + word *const TP=T+NA+2+NB; + + // copy B into TB and normalize it so that TB has highest bit set to 1 + unsigned shiftWords = (B[NB-1]==0); + TB[0] = TB[NB-1] = 0; + CopyWords(TB+shiftWords, B, NB-shiftWords); + unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); + ShiftWordsLeftByBits(TB, NB, shiftBits); + + // copy A into TA and normalize it + TA[0] = TA[NA] = TA[NA+1] = 0; + CopyWords(TA+shiftWords, A, NA); + ShiftWordsLeftByBits(TA, NA+2, shiftBits); + + if (TA[NA+1]==0 && TA[NA] <= 1) + { + Q[NA-NB+1] = Q[NA-NB] = 0; + while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0) + { + TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB); + ++Q[NA-NB]; + } + } + else + { + NA+=2; + } + + word BT[2]; + BT[0] = TB[NB-2] + 1; + BT[1] = TB[NB-1] + (BT[0]==0); + + // start reducing TA mod TB, 2 words at a time + for (unsigned i=NA-2; i>=NB; i-=2) + { + AtomicDivide(Q+i-NB, TA+i-2, BT); + CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB); + } + + // copy TA into R, and denormalize it + CopyWords(R, TA+shiftWords, NB); + ShiftWordsRightByBits(R, NB, shiftBits); +} + + +void PositiveDivide(Integer& remainder, Integer& quotient, + const Integer& a, const Integer& b) +{ + unsigned aSize = a.WordCount(); + unsigned bSize = b.WordCount(); + + if (a.PositiveCompare(b) == -1) + { + remainder = a; + remainder.sign_ = Integer::POSITIVE; + quotient = Integer::Zero(); + return; + } + + aSize += aSize%2; // round up to next even number + bSize += bSize%2; + + remainder.reg_.CleanNew(RoundupSize(bSize)); + remainder.sign_ = Integer::POSITIVE; + quotient.reg_.CleanNew(RoundupSize(aSize-bSize+2)); + quotient.sign_ = Integer::POSITIVE; + + AlignedWordBlock T(aSize+2*bSize+4); + Divide(remainder.reg_.get_buffer(), quotient.reg_.get_buffer(), + T.get_buffer(), a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), + bSize); +} + +void Integer::Divide(Integer &remainder, Integer "ient, + const Integer ÷nd, const Integer &divisor) +{ + PositiveDivide(remainder, quotient, dividend, divisor); + + if (dividend.IsNegative()) + { + quotient.Negate(); + if (remainder.NotZero()) + { + --quotient; + remainder = divisor.AbsoluteValue() - remainder; + } + } + + if (divisor.IsNegative()) + quotient.Negate(); +} + +void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, + unsigned int n) +{ + q = a; + q >>= n; + + const unsigned int wordCount = BitsToWords(n); + if (wordCount <= a.WordCount()) + { + r.reg_.resize(RoundupSize(wordCount)); + CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), wordCount); + SetWords(r.reg_+wordCount, 0, r.reg_.size()-wordCount); + if (n % WORD_BITS != 0) + r.reg_[wordCount-1] %= (word(1) << (n % WORD_BITS)); + } + else + { + r.reg_.resize(RoundupSize(a.WordCount())); + CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), r.reg_.size()); + } + r.sign_ = POSITIVE; + + if (a.IsNegative() && r.NotZero()) + { + --q; + r = Power2(n) - r; + } +} + +Integer Integer::DividedBy(const Integer &b) const +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, *this, b); + return quotient; +} + +Integer Integer::Modulo(const Integer &b) const +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, *this, b); + return remainder; +} + +void Integer::Divide(word &remainder, Integer "ient, + const Integer ÷nd, word divisor) +{ + if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 + { + quotient = dividend >> (BitPrecision(divisor)-1); + remainder = dividend.reg_[0] & (divisor-1); + return; + } + + unsigned int i = dividend.WordCount(); + quotient.reg_.CleanNew(RoundupSize(i)); + remainder = 0; + while (i--) + { + quotient.reg_[i] = DWord(dividend.reg_[i], remainder) / divisor; + remainder = DWord(dividend.reg_[i], remainder) % divisor; + } + + if (dividend.NotNegative()) + quotient.sign_ = POSITIVE; + else + { + quotient.sign_ = NEGATIVE; + if (remainder) + { + --quotient; + remainder = divisor - remainder; + } + } +} + +Integer Integer::DividedBy(word b) const +{ + word remainder; + Integer quotient; + Integer::Divide(remainder, quotient, *this, b); + return quotient; +} + +word Integer::Modulo(word divisor) const +{ + word remainder; + + if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 + remainder = reg_[0] & (divisor-1); + else + { + unsigned int i = WordCount(); + + if (divisor <= 5) + { + DWord sum(0, 0); + while (i--) + sum += reg_[i]; + remainder = sum % divisor; + } + else + { + remainder = 0; + while (i--) + remainder = DWord(reg_[i], remainder) % divisor; + } + } + + if (IsNegative() && remainder) + remainder = divisor - remainder; + + return remainder; +} + + +Integer Integer::AbsoluteValue() const +{ + Integer result(*this); + result.sign_ = POSITIVE; + return result; +} + + +Integer Integer::SquareRoot() const +{ + if (!IsPositive()) + return Zero(); + + // overestimate square root + Integer x, y = Power2((BitCount()+1)/2); + + do + { + x = y; + y = (x + *this/x) >> 1; + } while (y=m) + return (*this%m).InverseMod(m); + + if (m.IsEven()) + { + if (!m || IsEven()) + return Zero(); // no inverse + if (*this == One()) + return One(); + + Integer u = m.InverseMod(*this); + return !u ? Zero() : (m*(*this-u)+1)/(*this); + } + + AlignedWordBlock T(m.reg_.size() * 4); + Integer r((word)0, m.reg_.size()); + unsigned k = AlmostInverse(r.reg_.get_buffer(), T.get_buffer(), + reg_.get_buffer(), reg_.size(), + m.reg_.get_buffer(), m.reg_.size()); + DivideByPower2Mod(r.reg_.get_buffer(), r.reg_.get_buffer(), k, + m.reg_.get_buffer(), m.reg_.size()); + return r; +} + +word Integer::InverseMod(const word mod) const +{ + word g0 = mod, g1 = *this % mod; + word v0 = 0, v1 = 1; + word y; + + while (g1) + { + if (g1 == 1) + return v1; + y = g0 / g1; + g0 = g0 % g1; + v0 += y * v1; + + if (!g0) + break; + if (g0 == 1) + return mod-v0; + y = g1 / g0; + g1 = g1 % g0; + v1 += y * v0; + } + return 0; +} + +// ********* ModArith stuff + +const Integer& ModularArithmetic::Half(const Integer &a) const +{ + if (a.reg_.size()==modulus.reg_.size()) + { + TaoCrypt::DivideByPower2Mod(result.reg_.begin(), a.reg_.begin(), 1, + modulus.reg_.begin(), a.reg_.size()); + return result; + } + else + return result1 = (a.IsEven() ? (a >> 1) : ((a+modulus) >> 1)); +} + +const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const +{ + if (a.reg_.size()==modulus.reg_.size() && + b.reg_.size()==modulus.reg_.size()) + { + if (TaoCrypt::Add(result.reg_.begin(), a.reg_.begin(), b.reg_.begin(), + a.reg_.size()) + || Compare(result.reg_.get_buffer(), modulus.reg_.get_buffer(), + a.reg_.size()) >= 0) + { + TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(), + modulus.reg_.begin(), a.reg_.size()); + } + return result; + } + else + { + result1 = a+b; + if (result1 >= modulus) + result1 -= modulus; + return result1; + } +} + +Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const +{ + if (a.reg_.size()==modulus.reg_.size() && + b.reg_.size()==modulus.reg_.size()) + { + if (TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), a.reg_.size()) + || Compare(a.reg_.get_buffer(), modulus.reg_.get_buffer(), + a.reg_.size()) >= 0) + { + TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(), + modulus.reg_.get_buffer(), a.reg_.size()); + } + } + else + { + a+=b; + if (a>=modulus) + a-=modulus; + } + + return a; +} + +const Integer& ModularArithmetic::Subtract(const Integer &a, + const Integer &b) const +{ + if (a.reg_.size()==modulus.reg_.size() && + b.reg_.size()==modulus.reg_.size()) + { + if (TaoCrypt::Subtract(result.reg_.begin(), a.reg_.begin(), + b.reg_.begin(), a.reg_.size())) + TaoCrypt::Add(result.reg_.begin(), result.reg_.begin(), + modulus.reg_.begin(), a.reg_.size()); + return result; + } + else + { + result1 = a-b; + if (result1.IsNegative()) + result1 += modulus; + return result1; + } +} + +Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const +{ + if (a.reg_.size()==modulus.reg_.size() && + b.reg_.size()==modulus.reg_.size()) + { + if (TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(), + b.reg_.get_buffer(), a.reg_.size())) + TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(), + modulus.reg_.get_buffer(), a.reg_.size()); + } + else + { + a-=b; + if (a.IsNegative()) + a+=modulus; + } + + return a; +} + +const Integer& ModularArithmetic::Inverse(const Integer &a) const +{ + if (!a) + return a; + + CopyWords(result.reg_.begin(), modulus.reg_.begin(), modulus.reg_.size()); + if (TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(), + a.reg_.begin(), a.reg_.size())) + Decrement(result.reg_.begin()+a.reg_.size(), 1, + modulus.reg_.size()-a.reg_.size()); + + return result; +} + +Integer ModularArithmetic::CascadeExponentiate(const Integer &x, + const Integer &e1, const Integer &y, const Integer &e2) const +{ + if (modulus.IsOdd()) + { + MontgomeryRepresentation dr(modulus); + return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, + dr.ConvertIn(y), e2)); + } + else + return AbstractRing::CascadeExponentiate(x, e1, y, e2); +} + +void ModularArithmetic::SimultaneousExponentiate(Integer *results, + const Integer &base, const Integer *exponents, + unsigned int exponentsCount) const +{ + if (modulus.IsOdd()) + { + MontgomeryRepresentation dr(modulus); + dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents, + exponentsCount); + for (unsigned int i=0; i + +namespace TaoCrypt { + + +MD2::MD2() + : X_(X_SIZE), C_(BLOCK_SIZE), buffer_(BLOCK_SIZE) +{ + Init(); +} + +void MD2::Init() +{ + memset(X_.get_buffer(), 0, X_SIZE); + memset(C_.get_buffer(), 0, BLOCK_SIZE); + memset(buffer_.get_buffer(), 0, BLOCK_SIZE); + count_ = 0; +} + + +void MD2::Update(const byte* data, word32 len) +{ + + static const byte S[256] = + { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 + }; + + while (len) { + word32 L = (PAD_SIZE - count_) < len ? (PAD_SIZE - count_) : len; + memcpy(buffer_.get_buffer() + count_, data, L); + count_ += L; + data += L; + len -= L; + + if (count_==PAD_SIZE) { + count_ = 0; + memcpy(X_.get_buffer() + PAD_SIZE, buffer_.get_buffer(), PAD_SIZE); + byte t = C_[15]; + + int i; + for(i = 0; i < PAD_SIZE; i++) { + X_[32 + i] = X_[PAD_SIZE + i] ^ X_[i]; + t = C_[i] ^= S[buffer_[i] ^ t]; + } + + t=0; + for(i = 0; i < 18; i++) { + for(int j = 0; j < X_SIZE; j += 8) { + t = X_[j+0] ^= S[t]; + t = X_[j+1] ^= S[t]; + t = X_[j+2] ^= S[t]; + t = X_[j+3] ^= S[t]; + t = X_[j+4] ^= S[t]; + t = X_[j+5] ^= S[t]; + t = X_[j+6] ^= S[t]; + t = X_[j+7] ^= S[t]; + } + t = (t + i) & 0xFF; + } + } + } +} + + +void MD2::Final(byte *hash) +{ + byte padding[BLOCK_SIZE]; + word32 padLen = PAD_SIZE - count_; + + for (word32 i = 0; i < padLen; i++) + padding[i] = static_cast(padLen); + + Update(padding, padLen); + Update(C_.get_buffer(), BLOCK_SIZE); + + memcpy(hash, X_.get_buffer(), DIGEST_SIZE); + + Init(); +} + + + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/md4.cpp b/mysql/extra/yassl/taocrypt/src/md4.cpp new file mode 100644 index 0000000..9364a1c --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/md4.cpp @@ -0,0 +1,157 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* based on Wei Dai's md4.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "md4.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + +namespace TaoCrypt { + +void MD4::Init() +{ + digest_[0] = 0x67452301L; + digest_[1] = 0xefcdab89L; + digest_[2] = 0x98badcfeL; + digest_[3] = 0x10325476L; + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + + +MD4::MD4(const MD4& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32), + BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + +MD4& MD4::operator= (const MD4& that) +{ + MD4 tmp(that); + Swap(tmp); + + return *this; +} + + +void MD4::Swap(MD4& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +void MD4::Transform() +{ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + + word32 A, B, C, D; + + A = digest_[0]; + B = digest_[1]; + C = digest_[2]; + D = digest_[3]; + +#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+buffer_[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function +#define function(a,b,c,d,k,s) a=rotlFixed(a+G(b,c,d)+buffer_[k]+0x5a827999,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function +#define function(a,b,c,d,k,s) a=rotlFixed(a+H(b,c,d)+buffer_[k]+0x6ed9eba1,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + digest_[0] += A; + digest_[1] += B; + digest_[2] += C; + digest_[3] += D; +} + + +} // namespace + diff --git a/mysql/extra/yassl/taocrypt/src/md5.cpp b/mysql/extra/yassl/taocrypt/src/md5.cpp new file mode 100644 index 0000000..45cfa8a --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/md5.cpp @@ -0,0 +1,506 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* based on Wei Dai's md5.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "md5.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + + +namespace TaoCrypt { + +void MD5::Init() +{ + digest_[0] = 0x67452301L; + digest_[1] = 0xefcdab89L; + digest_[2] = 0x98badcfeL; + digest_[3] = 0x10325476L; + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + + +MD5::MD5(const MD5& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32), + BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + +MD5& MD5::operator= (const MD5& that) +{ + MD5 tmp(that); + Swap(tmp); + + return *this; +} + + +void MD5::Swap(MD5& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +#ifdef DO_MD5_ASM + +// Update digest with data of size len +void MD5::Update(const byte* data, word32 len) +{ + if (!isMMX) { + HASHwithTransform::Update(data, len); + return; + } + + byte* local = reinterpret_cast(buffer_); + + // remove buffered data if possible + if (buffLen_) { + word32 add = min(len, BLOCK_SIZE - buffLen_); + memcpy(&local[buffLen_], data, add); + + buffLen_ += add; + data += add; + len -= add; + + if (buffLen_ == BLOCK_SIZE) { + Transform(); + AddLength(BLOCK_SIZE); + buffLen_ = 0; + } + } + + // at once for asm + if (buffLen_ == 0) { + word32 times = len / BLOCK_SIZE; + if (times) { + AsmTransform(data, times); + const word32 add = BLOCK_SIZE * times; + AddLength(add); + len -= add; + data += add; + } + } + + // cache any data left + if (len) { + memcpy(&local[buffLen_], data, len); + buffLen_ += len; + } +} + + + + +/* + // w = rotlFixed(w + f(x, y, z) + index[edi] + data, s) + x +#define ASMMD5STEP(f, w, x, y, z, index, data, s) \ + f(x, y, z) \ + AS2( mov ebp, [edi + index * 4] ) \ + AS2( lea w, [esi + w + data] ) \ + AS2( add w, ebp ) \ + AS2( rol w, s ) \ + AS2( add w, x ) + + + // F1(x, y, z) (z ^ (x & (y ^ z))) + // place in esi +#define ASMF1(x, y, z) \ + AS2( mov esi, y ) \ + AS2( xor esi, z ) \ + AS2( and esi, x ) \ + AS2( xor esi, z ) + + +#define ASMF2(x, y, z) ASMF1(z, x, y) + + + // F3(x ^ y ^ z) + // place in esi +#define ASMF3(x, y, z) \ + AS2( mov esi, x ) \ + AS2( xor esi, y ) \ + AS2( xor esi, z ) + + + + // F4(x, y, z) (y ^ (x | ~z)) + // place in esi +#define ASMF4(x, y, z) \ + AS2( mov esi, z ) \ + AS1( not esi ) \ + AS2( or esi, x ) \ + AS2( xor esi, y ) +*/ + + + // combine above ASMMD5STEP(f w/ each f ASMF1 - F4 + + // esi already set up, after using set for next round + // ebp already set up, set up using next round index + +#define MD5STEP1(w, x, y, z, index, data, s) \ + AS2( xor esi, z ) \ + AS2( and esi, x ) \ + AS2( lea w, [ebp + w + data] ) \ + AS2( xor esi, z ) \ + AS2( add w, esi ) \ + AS2( mov esi, x ) \ + AS2( rol w, s ) \ + AS2( mov ebp, [edi + index * 4] ) \ + AS2( add w, x ) + +#define MD5STEP2(w, x, y, z, index, data, s) \ + AS2( xor esi, x ) \ + AS2( and esi, z ) \ + AS2( lea w, [ebp + w + data] ) \ + AS2( xor esi, y ) \ + AS2( add w, esi ) \ + AS2( mov esi, x ) \ + AS2( rol w, s ) \ + AS2( mov ebp, [edi + index * 4] ) \ + AS2( add w, x ) + + +#define MD5STEP3(w, x, y, z, index, data, s) \ + AS2( xor esi, z ) \ + AS2( lea w, [ebp + w + data] ) \ + AS2( xor esi, x ) \ + AS2( add w, esi ) \ + AS2( mov esi, x ) \ + AS2( rol w, s ) \ + AS2( mov ebp, [edi + index * 4] ) \ + AS2( add w, x ) + + +#define MD5STEP4(w, x, y, z, index, data, s) \ + AS2( or esi, x ) \ + AS2( lea w, [ebp + w + data] ) \ + AS2( xor esi, y ) \ + AS2( add w, esi ) \ + AS2( mov esi, y ) \ + AS2( rol w, s ) \ + AS1( not esi ) \ + AS2( mov ebp, [edi + index * 4] ) \ + AS2( add w, x ) + + + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void MD5::AsmTransform(const byte* data, word32 times) +{ +#ifdef __GNUC__ + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + + #define PROLOG() \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + "push ebx;" \ + "push ebp;" + #define EPILOG() \ + "pop ebp;" \ + "pop ebx;" \ + "emms;" \ + ".att_syntax;" \ + : \ + : "c" (this), "D" (data), "a" (times) \ + : "%esi", "%edx", "memory", "cc" \ + ); + +#else + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + + #define PROLOG() \ + AS1( push ebp ) \ + AS2( mov ebp, esp ) \ + AS2( movd mm3, edi ) \ + AS2( movd mm4, ebx ) \ + AS2( movd mm5, esi ) \ + AS2( movd mm6, ebp ) \ + AS2( mov edi, DWORD PTR [ebp + 8] ) \ + AS2( mov eax, DWORD PTR [ebp + 12] ) + + #define EPILOG() \ + AS2( movd ebp, mm6 ) \ + AS2( movd esi, mm5 ) \ + AS2( movd ebx, mm4 ) \ + AS2( movd edi, mm3 ) \ + AS2( mov esp, ebp ) \ + AS1( pop ebp ) \ + AS1( emms ) \ + AS1( ret 8 ) + +#endif + + + PROLOG() + + AS2( mov esi, ecx ) + + #ifdef OLD_GCC_OFFSET + AS2( add esi, 20 ) // digest_[0] + #else + AS2( add esi, 16 ) // digest_[0] + #endif + + AS2( movd mm2, eax ) // store times_ + AS2( movd mm1, esi ) // store digest_ + + AS2( mov eax, [esi] ) // a + AS2( mov ebx, [esi + 4] ) // b + AS2( mov ecx, [esi + 8] ) // c + AS2( mov edx, [esi + 12] ) // d + +#ifdef _MSC_VER + AS1( loopStart: ) // loopStart +#else + AS1( 0: ) // loopStart for some gas (need numeric for jump back +#endif + + // set up + AS2( mov esi, ecx ) + AS2( mov ebp, [edi] ) + + MD5STEP1( eax, ebx, ecx, edx, 1, 0xd76aa478, 7) + MD5STEP1( edx, eax, ebx, ecx, 2, 0xe8c7b756, 12) + MD5STEP1( ecx, edx, eax, ebx, 3, 0x242070db, 17) + MD5STEP1( ebx, ecx, edx, eax, 4, 0xc1bdceee, 22) + MD5STEP1( eax, ebx, ecx, edx, 5, 0xf57c0faf, 7) + MD5STEP1( edx, eax, ebx, ecx, 6, 0x4787c62a, 12) + MD5STEP1( ecx, edx, eax, ebx, 7, 0xa8304613, 17) + MD5STEP1( ebx, ecx, edx, eax, 8, 0xfd469501, 22) + MD5STEP1( eax, ebx, ecx, edx, 9, 0x698098d8, 7) + MD5STEP1( edx, eax, ebx, ecx, 10, 0x8b44f7af, 12) + MD5STEP1( ecx, edx, eax, ebx, 11, 0xffff5bb1, 17) + MD5STEP1( ebx, ecx, edx, eax, 12, 0x895cd7be, 22) + MD5STEP1( eax, ebx, ecx, edx, 13, 0x6b901122, 7) + MD5STEP1( edx, eax, ebx, ecx, 14, 0xfd987193, 12) + MD5STEP1( ecx, edx, eax, ebx, 15, 0xa679438e, 17) + MD5STEP1( ebx, ecx, edx, eax, 1, 0x49b40821, 22) + + MD5STEP2( eax, ebx, ecx, edx, 6, 0xf61e2562, 5) + MD5STEP2( edx, eax, ebx, ecx, 11, 0xc040b340, 9) + MD5STEP2( ecx, edx, eax, ebx, 0, 0x265e5a51, 14) + MD5STEP2( ebx, ecx, edx, eax, 5, 0xe9b6c7aa, 20) + MD5STEP2( eax, ebx, ecx, edx, 10, 0xd62f105d, 5) + MD5STEP2( edx, eax, ebx, ecx, 15, 0x02441453, 9) + MD5STEP2( ecx, edx, eax, ebx, 4, 0xd8a1e681, 14) + MD5STEP2( ebx, ecx, edx, eax, 9, 0xe7d3fbc8, 20) + MD5STEP2( eax, ebx, ecx, edx, 14, 0x21e1cde6, 5) + MD5STEP2( edx, eax, ebx, ecx, 3, 0xc33707d6, 9) + MD5STEP2( ecx, edx, eax, ebx, 8, 0xf4d50d87, 14) + MD5STEP2( ebx, ecx, edx, eax, 13, 0x455a14ed, 20) + MD5STEP2( eax, ebx, ecx, edx, 2, 0xa9e3e905, 5) + MD5STEP2( edx, eax, ebx, ecx, 7, 0xfcefa3f8, 9) + MD5STEP2( ecx, edx, eax, ebx, 12, 0x676f02d9, 14) + MD5STEP2( ebx, ecx, edx, eax, 5, 0x8d2a4c8a, 20) + + MD5STEP3( eax, ebx, ecx, edx, 8, 0xfffa3942, 4) + MD5STEP3( edx, eax, ebx, ecx, 11, 0x8771f681, 11) + MD5STEP3( ecx, edx, eax, ebx, 14, 0x6d9d6122, 16) + MD5STEP3( ebx, ecx, edx, eax, 1, 0xfde5380c, 23) + MD5STEP3( eax, ebx, ecx, edx, 4, 0xa4beea44, 4) + MD5STEP3( edx, eax, ebx, ecx, 7, 0x4bdecfa9, 11) + MD5STEP3( ecx, edx, eax, ebx, 10, 0xf6bb4b60, 16) + MD5STEP3( ebx, ecx, edx, eax, 13, 0xbebfbc70, 23) + MD5STEP3( eax, ebx, ecx, edx, 0, 0x289b7ec6, 4) + MD5STEP3( edx, eax, ebx, ecx, 3, 0xeaa127fa, 11) + MD5STEP3( ecx, edx, eax, ebx, 6, 0xd4ef3085, 16) + MD5STEP3( ebx, ecx, edx, eax, 9, 0x04881d05, 23) + MD5STEP3( eax, ebx, ecx, edx, 12, 0xd9d4d039, 4) + MD5STEP3( edx, eax, ebx, ecx, 15, 0xe6db99e5, 11) + MD5STEP3( ecx, edx, eax, ebx, 2, 0x1fa27cf8, 16) + MD5STEP3( ebx, ecx, edx, eax, 0, 0xc4ac5665, 23) + + // setup + AS2( mov esi, edx ) + AS1( not esi ) + + MD5STEP4( eax, ebx, ecx, edx, 7, 0xf4292244, 6) + MD5STEP4( edx, eax, ebx, ecx, 14, 0x432aff97, 10) + MD5STEP4( ecx, edx, eax, ebx, 5, 0xab9423a7, 15) + MD5STEP4( ebx, ecx, edx, eax, 12, 0xfc93a039, 21) + MD5STEP4( eax, ebx, ecx, edx, 3, 0x655b59c3, 6) + MD5STEP4( edx, eax, ebx, ecx, 10, 0x8f0ccc92, 10) + MD5STEP4( ecx, edx, eax, ebx, 1, 0xffeff47d, 15) + MD5STEP4( ebx, ecx, edx, eax, 8, 0x85845dd1, 21) + MD5STEP4( eax, ebx, ecx, edx, 15, 0x6fa87e4f, 6) + MD5STEP4( edx, eax, ebx, ecx, 6, 0xfe2ce6e0, 10) + MD5STEP4( ecx, edx, eax, ebx, 13, 0xa3014314, 15) + MD5STEP4( ebx, ecx, edx, eax, 4, 0x4e0811a1, 21) + MD5STEP4( eax, ebx, ecx, edx, 11, 0xf7537e82, 6) + MD5STEP4( edx, eax, ebx, ecx, 2, 0xbd3af235, 10) + MD5STEP4( ecx, edx, eax, ebx, 9, 0x2ad7d2bb, 15) + MD5STEP4( ebx, ecx, edx, eax, 9, 0xeb86d391, 21) + + AS2( movd esi, mm1 ) // digest_ + + AS2( add [esi], eax ) // write out + AS2( add [esi + 4], ebx ) + AS2( add [esi + 8], ecx ) + AS2( add [esi + 12], edx ) + + AS2( add edi, 64 ) + + AS2( mov eax, [esi] ) + AS2( mov ebx, [esi + 4] ) + AS2( mov ecx, [esi + 8] ) + AS2( mov edx, [esi + 12] ) + + AS2( movd ebp, mm2 ) // times + AS1( dec ebp ) + AS2( movd mm2, ebp ) +#ifdef _MSC_VER + AS1( jnz loopStart ) // loopStart +#else + AS1( jnz 0b ) // loopStart +#endif + + + EPILOG() +} + + +#endif // DO_MD5_ASM + + +void MD5::Transform() +{ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + // Copy context->state[] to working vars + word32 a = digest_[0]; + word32 b = digest_[1]; + word32 c = digest_[2]; + word32 d = digest_[3]; + + MD5STEP(F1, a, b, c, d, buffer_[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, buffer_[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, buffer_[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, buffer_[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, buffer_[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, buffer_[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, buffer_[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, buffer_[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, buffer_[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, buffer_[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, buffer_[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, buffer_[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, buffer_[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, buffer_[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, buffer_[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, buffer_[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, buffer_[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, buffer_[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, buffer_[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, buffer_[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, buffer_[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, buffer_[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, buffer_[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, buffer_[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, buffer_[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, buffer_[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, buffer_[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, buffer_[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, buffer_[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, buffer_[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, buffer_[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, buffer_[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, buffer_[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, buffer_[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, buffer_[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, buffer_[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, buffer_[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, buffer_[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, buffer_[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, buffer_[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, buffer_[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, buffer_[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, buffer_[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, buffer_[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, buffer_[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, buffer_[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, buffer_[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, buffer_[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, buffer_[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, buffer_[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, buffer_[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, buffer_[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, buffer_[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, buffer_[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, buffer_[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, buffer_[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, buffer_[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, buffer_[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, buffer_[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, buffer_[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, buffer_[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, buffer_[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, buffer_[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, buffer_[9] + 0xeb86d391, 21); + + // Add the working vars back into digest state[] + digest_[0] += a; + digest_[1] += b; + digest_[2] += c; + digest_[3] += d; + + // Wipe variables + a = b = c = d = 0; +} + + +} // namespace + diff --git a/mysql/extra/yassl/taocrypt/src/misc.cpp b/mysql/extra/yassl/taocrypt/src/misc.cpp new file mode 100644 index 0000000..b576d3d --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/misc.cpp @@ -0,0 +1,297 @@ +/* + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's misc.cpp from CryptoPP */ + + +#include "runtime.hpp" +#include "misc.hpp" + + +#ifdef __GNUC__ + #include + #include +#endif + +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + +namespace STL = STL_NAMESPACE; + + +#ifdef YASSL_PURE_C + + void* operator new(size_t sz, TaoCrypt::new_t) + { + void* ptr = malloc(sz ? sz : 1); + if (!ptr) abort(); + + return ptr; + } + + + void operator delete(void* ptr, TaoCrypt::new_t) + { + if (ptr) free(ptr); + } + + + void* operator new[](size_t sz, TaoCrypt::new_t nt) + { + return ::operator new(sz, nt); + } + + + void operator delete[](void* ptr, TaoCrypt::new_t nt) + { + ::operator delete(ptr, nt); + } + + + /* uncomment to test + // make sure not using globals anywhere by forgetting to use overloaded + void* operator new(size_t sz); + + void operator delete(void* ptr); + + void* operator new[](size_t sz); + + void operator delete[](void* ptr); + */ + + + namespace TaoCrypt { + + new_t tc; // for library new + + } + +#ifdef __sun + +// Handler for pure virtual functions +namespace __Crun { + void pure_error() { + } +} + +#endif + +#if defined(__ICC) || defined(__INTEL_COMPILER) || (__GNUC__ > 2) + +extern "C" { + + int __cxa_pure_virtual() { + return 0; + } + +} // extern "C" + +#endif + +#endif // YASSL_PURE_C + + +namespace TaoCrypt { + + +inline void XorWords(word* r, const word* a, unsigned int n) +{ + for (unsigned int i=0; i> (i-1)*8) + break; + + return i; +} + + +unsigned int BitPrecision(word value) +{ + if (!value) + return 0; + + unsigned int l = 0, + h = 8 * sizeof(value); + + while (h-l > 1) + { + unsigned int t = (l+h)/2; + if (value >> t) + l = t; + else + h = t; + } + + return h; +} + + +word Crop(word value, unsigned int size) +{ + if (size < 8*sizeof(value)) + return (value & ((1L << size) - 1)); + else + return value; +} + + + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + + +bool HaveCpuId() +{ +#ifdef _MSC_VER + __try + { + __asm + { + mov eax, 0 + cpuid + } + } + __except (1) + { + return false; + } + return true; +#else + word32 eax, ebx; + __asm__ __volatile + ( + /* Put EFLAGS in eax and ebx */ + "pushf;" + "pushf;" + "pop %0;" + "movl %0,%1;" + + /* Flip the cpuid bit and store back in EFLAGS */ + "xorl $0x200000,%0;" + "push %0;" + "popf;" + + /* Read EFLAGS again */ + "pushf;" + "pop %0;" + "popf" + : "=r" (eax), "=r" (ebx) + : + : "cc" + ); + + if (eax == ebx) + return false; + return true; +#endif +} + + +void CpuId(word32 input, word32 *output) +{ +#ifdef __GNUC__ + __asm__ + ( + // save ebx in case -fPIC is being used + "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" + : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d"(output[3]) + : "a" (input) + ); +#else + __asm + { + mov eax, input + cpuid + mov edi, output + mov [edi], eax + mov [edi+4], ebx + mov [edi+8], ecx + mov [edi+12], edx + } +#endif +} + + +bool IsPentium() +{ + if (!HaveCpuId()) + return false; + + word32 cpuid[4]; + + CpuId(0, cpuid); + STL::swap(cpuid[2], cpuid[3]); + if (memcmp(cpuid+1, "GenuineIntel", 12) != 0) + return false; + + CpuId(1, cpuid); + byte family = ((cpuid[0] >> 8) & 0xf); + if (family < 5) + return false; + + return true; +} + + + +static bool IsMmx() +{ + if (!IsPentium()) + return false; + + word32 cpuid[4]; + + CpuId(1, cpuid); + if ((cpuid[3] & (1 << 23)) == 0) + return false; + + return true; +} + + +bool isMMX = IsMmx(); + + +#endif // TAOCRYPT_X86ASM_AVAILABLE + + + + +} // namespace + diff --git a/mysql/extra/yassl/taocrypt/src/rabbit.cpp b/mysql/extra/yassl/taocrypt/src/rabbit.cpp new file mode 100644 index 0000000..5e32f38 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/rabbit.cpp @@ -0,0 +1,255 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +#include "runtime.hpp" +#include "rabbit.hpp" + + + +namespace TaoCrypt { + + +#define U32V(x) (word32)(x) + + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverse((word32)x) +#else + #define LITTLE32(x) (x) +#endif + + +// local +namespace { + + +/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ +/* the upper 32 bits XOR the lower 32 bits */ +word32 RABBIT_g_func(word32 x) +{ + /* Temporary variables */ + word32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x&0xFFFF; + b = x>>16; + + /* Calculate high and low result of squaring */ + h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b; + l = x*x; + + /* Return high XOR low */ + return U32V(h^l); +} + + +} // namespace local + + +/* Calculate the next internal state */ +void Rabbit::NextState(RabbitCtx which) +{ + /* Temporary variables */ + word32 g[8], c_old[8], i; + + Ctx* ctx; + + if (which == Master) + ctx = &masterCtx_; + else + ctx = &workCtx_; + + /* Save old counter values */ + for (i=0; i<8; i++) + c_old[i] = ctx->c[i]; + + /* Calculate new counter values */ + ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry); + ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0])); + ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1])); + ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2])); + ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3])); + ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4])); + ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5])); + ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6])); + ctx->carry = (ctx->c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i=0;i<8;i++) + g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i])); + + /* Calculate new state values */ + ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16)); + ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]); + ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16)); + ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]); + ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16)); + ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]); + ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16)); + ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]); +} + + +/* IV setup */ +void Rabbit::SetIV(const byte* iv) +{ + /* Temporary variables */ + word32 i0, i1, i2, i3, i; + + /* Generate four subvectors */ + i0 = LITTLE32(*(word32*)(iv+0)); + i2 = LITTLE32(*(word32*)(iv+4)); + i1 = (i0>>16) | (i2&0xFFFF0000); + i3 = (i2<<16) | (i0&0x0000FFFF); + + /* Modify counter values */ + workCtx_.c[0] = masterCtx_.c[0] ^ i0; + workCtx_.c[1] = masterCtx_.c[1] ^ i1; + workCtx_.c[2] = masterCtx_.c[2] ^ i2; + workCtx_.c[3] = masterCtx_.c[3] ^ i3; + workCtx_.c[4] = masterCtx_.c[4] ^ i0; + workCtx_.c[5] = masterCtx_.c[5] ^ i1; + workCtx_.c[6] = masterCtx_.c[6] ^ i2; + workCtx_.c[7] = masterCtx_.c[7] ^ i3; + + /* Copy state variables */ + for (i=0; i<8; i++) + workCtx_.x[i] = masterCtx_.x[i]; + workCtx_.carry = masterCtx_.carry; + + /* Iterate the system four times */ + for (i=0; i<4; i++) + NextState(Work); +} + + +/* Key setup */ +void Rabbit::SetKey(const byte* key, const byte* iv) +{ + /* Temporary variables */ + word32 k0, k1, k2, k3, i; + + /* Generate four subkeys */ + k0 = LITTLE32(*(word32*)(key+ 0)); + k1 = LITTLE32(*(word32*)(key+ 4)); + k2 = LITTLE32(*(word32*)(key+ 8)); + k3 = LITTLE32(*(word32*)(key+12)); + + /* Generate initial state variables */ + masterCtx_.x[0] = k0; + masterCtx_.x[2] = k1; + masterCtx_.x[4] = k2; + masterCtx_.x[6] = k3; + masterCtx_.x[1] = U32V(k3<<16) | (k2>>16); + masterCtx_.x[3] = U32V(k0<<16) | (k3>>16); + masterCtx_.x[5] = U32V(k1<<16) | (k0>>16); + masterCtx_.x[7] = U32V(k2<<16) | (k1>>16); + + /* Generate initial counter values */ + masterCtx_.c[0] = rotlFixed(k2, 16); + masterCtx_.c[2] = rotlFixed(k3, 16); + masterCtx_.c[4] = rotlFixed(k0, 16); + masterCtx_.c[6] = rotlFixed(k1, 16); + masterCtx_.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); + masterCtx_.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); + masterCtx_.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); + masterCtx_.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); + + /* Clear carry bit */ + masterCtx_.carry = 0; + + /* Iterate the system four times */ + for (i=0; i<4; i++) + NextState(Master); + + /* Modify the counters */ + for (i=0; i<8; i++) + masterCtx_.c[i] ^= masterCtx_.x[(i+4)&0x7]; + + /* Copy master instance to work instance */ + for (i=0; i<8; i++) { + workCtx_.x[i] = masterCtx_.x[i]; + workCtx_.c[i] = masterCtx_.c[i]; + } + workCtx_.carry = masterCtx_.carry; + + if (iv) SetIV(iv); +} + + +/* Encrypt/decrypt a message of any size */ +void Rabbit::Process(byte* output, const byte* input, word32 msglen) +{ + /* Temporary variables */ + word32 i; + + /* Encrypt/decrypt all full blocks */ + while (msglen >= 16) { + /* Iterate the system */ + NextState(Work); + + /* Encrypt/decrypt 16 bytes of data */ + *(word32*)(output+ 0) = *(word32*)(input+ 0) ^ + LITTLE32(workCtx_.x[0] ^ (workCtx_.x[5]>>16) ^ + U32V(workCtx_.x[3]<<16)); + *(word32*)(output+ 4) = *(word32*)(input+ 4) ^ + LITTLE32(workCtx_.x[2] ^ (workCtx_.x[7]>>16) ^ + U32V(workCtx_.x[5]<<16)); + *(word32*)(output+ 8) = *(word32*)(input+ 8) ^ + LITTLE32(workCtx_.x[4] ^ (workCtx_.x[1]>>16) ^ + U32V(workCtx_.x[7]<<16)); + *(word32*)(output+12) = *(word32*)(input+12) ^ + LITTLE32(workCtx_.x[6] ^ (workCtx_.x[3]>>16) ^ + U32V(workCtx_.x[1]<<16)); + + /* Increment pointers and decrement length */ + input += 16; + output += 16; + msglen -= 16; + } + + /* Encrypt/decrypt remaining data */ + if (msglen) { + + word32 tmp[4]; + byte* buffer = (byte*)tmp; + + memset(tmp, 0, sizeof(tmp)); /* help static analysis */ + + /* Iterate the system */ + NextState(Work); + + /* Generate 16 bytes of pseudo-random data */ + tmp[0] = LITTLE32(workCtx_.x[0] ^ + (workCtx_.x[5]>>16) ^ U32V(workCtx_.x[3]<<16)); + tmp[1] = LITTLE32(workCtx_.x[2] ^ + (workCtx_.x[7]>>16) ^ U32V(workCtx_.x[5]<<16)); + tmp[2] = LITTLE32(workCtx_.x[4] ^ + (workCtx_.x[1]>>16) ^ U32V(workCtx_.x[7]<<16)); + tmp[3] = LITTLE32(workCtx_.x[6] ^ + (workCtx_.x[3]>>16) ^ U32V(workCtx_.x[1]<<16)); + + /* Encrypt/decrypt the data */ + for (i=0; i +#include + +#if defined(_WIN32) + #include + #include +#else + #include + #include + #include +#endif // _WIN32 + +namespace TaoCrypt { + + +// Get seed and key cipher +RandomNumberGenerator::RandomNumberGenerator() +{ + byte key[32]; + byte junk[256]; + + seed_.GenerateSeed(key, sizeof(key)); + cipher_.SetKey(key, sizeof(key)); + GenerateBlock(junk, sizeof(junk)); // rid initial state +} + + +// place a generated block in output +void RandomNumberGenerator::GenerateBlock(byte* output, word32 sz) +{ + memset(output, 0, sz); + cipher_.Process(output, output, sz); +} + + +byte RandomNumberGenerator::GenerateByte() +{ + byte b; + GenerateBlock(&b, 1); + + return b; +} + + +#if defined(_WIN32) + +/* The OS_Seed implementation for windows */ + +OS_Seed::OS_Seed() +{ + if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + error_.SetError(WINCRYPT_E); +} + + +OS_Seed::~OS_Seed() +{ + CryptReleaseContext(handle_, 0); +} + + +void OS_Seed::GenerateSeed(byte* output, word32 sz) +{ + if (!CryptGenRandom(handle_, sz, output)) + error_.SetError(CRYPTGEN_E); +} + + +#else + +/* The default OS_Seed implementation */ + +OS_Seed::OS_Seed() +{ + fd_ = open("/dev/urandom",O_RDONLY); + if (fd_ == -1) { + fd_ = open("/dev/random",O_RDONLY); + if (fd_ == -1) + error_.SetError(OPEN_RAN_E); + } +} + + +OS_Seed::~OS_Seed() +{ + close(fd_); +} + + +// may block +void OS_Seed::GenerateSeed(byte* output, word32 sz) +{ + while (sz) { + int len = read(fd_, output, sz); + if (len == -1) { + error_.SetError(READ_RAN_E); + return; + } + + sz -= len; + output += len; + + if (sz) + sleep(1); + } +} + +#endif // _WIN32 + + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/ripemd.cpp b/mysql/extra/yassl/taocrypt/src/ripemd.cpp new file mode 100644 index 0000000..5d03dc6 --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/ripemd.cpp @@ -0,0 +1,844 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +/* based on Wei Dai's ripemd.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "ripemd.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + + +namespace TaoCrypt { + +void RIPEMD160::Init() +{ + digest_[0] = 0x67452301L; + digest_[1] = 0xefcdab89L; + digest_[2] = 0x98badcfeL; + digest_[3] = 0x10325476L; + digest_[4] = 0xc3d2e1f0L; + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + + +RIPEMD160::RIPEMD160(const RIPEMD160& that) + : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + + +RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that) +{ + RIPEMD160 tmp(that); + Swap(tmp); + + return *this; +} + + +void RIPEMD160::Swap(RIPEMD160& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +#ifdef DO_RIPEMD_ASM + +// Update digest with data of size len +void RIPEMD160::Update(const byte* data, word32 len) +{ + if (!isMMX) { + HASHwithTransform::Update(data, len); + return; + } + + byte* local = reinterpret_cast(buffer_); + + // remove buffered data if possible + if (buffLen_) { + word32 add = min(len, BLOCK_SIZE - buffLen_); + memcpy(&local[buffLen_], data, add); + + buffLen_ += add; + data += add; + len -= add; + + if (buffLen_ == BLOCK_SIZE) { + Transform(); + AddLength(BLOCK_SIZE); + buffLen_ = 0; + } + } + + // all at once for asm + if (buffLen_ == 0) { + word32 times = len / BLOCK_SIZE; + if (times) { + AsmTransform(data, times); + const word32 add = BLOCK_SIZE * times; + AddLength(add); + len -= add; + data += add; + } + } + + // cache any data left + if (len) { + memcpy(&local[buffLen_], data, len); + buffLen_ += len; + } +} + +#endif // DO_RIPEMD_ASM + + +// for all +#define F(x, y, z) (x ^ y ^ z) +#define G(x, y, z) (z ^ (x & (y^z))) +#define H(x, y, z) (z ^ (x | ~y)) +#define I(x, y, z) (y ^ (z & (x^y))) +#define J(x, y, z) (x ^ (y | ~z)) + +#define k0 0 +#define k1 0x5a827999 +#define k2 0x6ed9eba1 +#define k3 0x8f1bbcdc +#define k4 0xa953fd4e +#define k5 0x50a28be6 +#define k6 0x5c4dd124 +#define k7 0x6d703ef3 +#define k8 0x7a6d76e9 +#define k9 0 + +// for 160 and 320 +#define Subround(f, a, b, c, d, e, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlFixed((word32)a, s) + e;\ + c = rotlFixed((word32)c, 10U) + + +void RIPEMD160::Transform() +{ + unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; + a1 = a2 = digest_[0]; + b1 = b2 = digest_[1]; + c1 = c2 = digest_[2]; + d1 = d2 = digest_[3]; + e1 = e2 = digest_[4]; + + Subround(F, a1, b1, c1, d1, e1, buffer_[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, buffer_[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, buffer_[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, buffer_[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, buffer_[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, buffer_[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, buffer_[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, buffer_[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, buffer_[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, buffer_[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, buffer_[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, buffer_[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, buffer_[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, buffer_[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, buffer_[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, buffer_[15], 8, k0); + + Subround(G, e1, a1, b1, c1, d1, buffer_[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, buffer_[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, buffer_[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, buffer_[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, buffer_[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, buffer_[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, buffer_[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, buffer_[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, buffer_[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, buffer_[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, buffer_[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, buffer_[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, buffer_[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, buffer_[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, buffer_[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, buffer_[ 8], 12, k1); + + Subround(H, d1, e1, a1, b1, c1, buffer_[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, buffer_[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, buffer_[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, buffer_[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, buffer_[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, buffer_[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, buffer_[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, buffer_[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, buffer_[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, buffer_[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, buffer_[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, buffer_[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, buffer_[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, buffer_[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, buffer_[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, buffer_[12], 5, k2); + + Subround(I, c1, d1, e1, a1, b1, buffer_[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, buffer_[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, buffer_[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, buffer_[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, buffer_[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, buffer_[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, buffer_[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, buffer_[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, buffer_[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, buffer_[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, buffer_[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, buffer_[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, buffer_[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, buffer_[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, buffer_[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, buffer_[ 2], 12, k3); + + Subround(J, b1, c1, d1, e1, a1, buffer_[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, buffer_[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, buffer_[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, buffer_[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, buffer_[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, buffer_[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, buffer_[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, buffer_[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, buffer_[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, buffer_[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, buffer_[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, buffer_[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, buffer_[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, buffer_[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, buffer_[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, buffer_[13], 6, k4); + + Subround(J, a2, b2, c2, d2, e2, buffer_[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, buffer_[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, buffer_[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, buffer_[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, buffer_[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, buffer_[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, buffer_[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, buffer_[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, buffer_[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, buffer_[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, buffer_[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, buffer_[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, buffer_[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, buffer_[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, buffer_[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, buffer_[12], 6, k5); + + Subround(I, e2, a2, b2, c2, d2, buffer_[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, buffer_[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, buffer_[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, buffer_[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, buffer_[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, buffer_[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, buffer_[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, buffer_[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, buffer_[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, buffer_[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, buffer_[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, buffer_[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, buffer_[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, buffer_[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, buffer_[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, buffer_[ 2], 11, k6); + + Subround(H, d2, e2, a2, b2, c2, buffer_[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, buffer_[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, buffer_[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, buffer_[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, buffer_[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, buffer_[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, buffer_[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, buffer_[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, buffer_[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, buffer_[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, buffer_[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, buffer_[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, buffer_[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, buffer_[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, buffer_[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, buffer_[13], 5, k7); + + Subround(G, c2, d2, e2, a2, b2, buffer_[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, buffer_[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, buffer_[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, buffer_[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, buffer_[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, buffer_[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, buffer_[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, buffer_[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, buffer_[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, buffer_[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, buffer_[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, buffer_[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, buffer_[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, buffer_[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, buffer_[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, buffer_[14], 8, k8); + + Subround(F, b2, c2, d2, e2, a2, buffer_[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, buffer_[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, buffer_[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, buffer_[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, buffer_[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, buffer_[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, buffer_[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, buffer_[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, buffer_[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, buffer_[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, buffer_[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, buffer_[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, buffer_[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, buffer_[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, buffer_[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, buffer_[11], 11, k9); + + c1 = digest_[1] + c1 + d2; + digest_[1] = digest_[2] + d1 + e2; + digest_[2] = digest_[3] + e1 + a2; + digest_[3] = digest_[4] + a1 + b2; + digest_[4] = digest_[0] + b1 + c2; + digest_[0] = c1; +} + + +#ifdef DO_RIPEMD_ASM + +/* + // F(x ^ y ^ z) + // place in esi +#define ASMF(x, y, z) \ + AS2( mov esi, x ) \ + AS2( xor esi, y ) \ + AS2( xor esi, z ) + + + // G(z ^ (x & (y^z))) + // place in esi +#define ASMG(x, y, z) \ + AS2( mov esi, z ) \ + AS2( xor esi, y ) \ + AS2( and esi, x ) \ + AS2( xor esi, z ) + + + // H(z ^ (x | ~y)) + // place in esi +#define ASMH(x, y, z) \ + AS2( mov esi, y ) \ + AS1( not esi ) \ + AS2( or esi, x ) \ + AS2( xor esi, z ) + + + // I(y ^ (z & (x^y))) + // place in esi +#define ASMI(x, y, z) \ + AS2( mov esi, y ) \ + AS2( xor esi, x ) \ + AS2( and esi, z ) \ + AS2( xor esi, y ) + + + // J(x ^ (y | ~z))) + // place in esi +#define ASMJ(x, y, z) \ + AS2( mov esi, z ) \ + AS1( not esi ) \ + AS2( or esi, y ) \ + AS2( xor esi, x ) + + +// for 160 and 320 +// #define ASMSubround(f, a, b, c, d, e, i, s, k) +// a += f(b, c, d) + data[i] + k; +// a = rotlFixed((word32)a, s) + e; +// c = rotlFixed((word32)c, 10U) + +#define ASMSubround(f, a, b, c, d, e, index, s, k) \ + // a += f(b, c, d) + data[i] + k \ + AS2( mov esp, [edi + index * 4] ) \ + f(b, c, d) \ + AS2( add esi, k ) \ + AS2( add esi, esp ) \ + AS2( add a, esi ) \ + // a = rotlFixed((word32)a, s) + e \ + AS2( rol a, s ) \ + AS2( rol c, 10 ) \ + // c = rotlFixed((word32)c, 10U) \ + AS2( add a, e ) +*/ + + +// combine F into subround w/ setup +// esi already has c, setup for next round when done +// esp already has edi[index], setup for next round when done + +#define ASMSubroundF(a, b, c, d, e, index, s) \ + /* a += (b ^ c ^ d) + data[i] + k */ \ + AS2( xor esi, b ) \ + AS2( add a, [edi + index * 4] ) \ + AS2( xor esi, d ) \ + AS2( add a, esi ) \ + /* a = rotlFixed((word32)a, s) + e */ \ + AS2( mov esi, b ) \ + AS2( rol a, s ) \ + /* c = rotlFixed((word32)c, 10U) */ \ + AS2( rol c, 10 ) \ + AS2( add a, e ) + + +// combine G into subround w/ setup +// esi already has c, setup for next round when done +// esp already has edi[index], setup for next round when done + +#define ASMSubroundG(a, b, c, d, e, index, s, k) \ + /* a += (d ^ (b & (c^d))) + data[i] + k */ \ + AS2( xor esi, d ) \ + AS2( and esi, b ) \ + AS2( add a, [edi + index * 4] ) \ + AS2( xor esi, d ) \ + AS2( lea a, [esi + a + k] ) \ + /* a = rotlFixed((word32)a, s) + e */ \ + AS2( mov esi, b ) \ + AS2( rol a, s ) \ + /* c = rotlFixed((word32)c, 10U) */ \ + AS2( rol c, 10 ) \ + AS2( add a, e ) + + +// combine H into subround w/ setup +// esi already has c, setup for next round when done +// esp already has edi[index], setup for next round when done + +#define ASMSubroundH(a, b, c, d, e, index, s, k) \ + /* a += (d ^ (b | ~c)) + data[i] + k */ \ + AS1( not esi ) \ + AS2( or esi, b ) \ + AS2( add a, [edi + index * 4] ) \ + AS2( xor esi, d ) \ + AS2( lea a, [esi + a + k] ) \ + /* a = rotlFixed((word32)a, s) + e */ \ + AS2( mov esi, b ) \ + AS2( rol a, s ) \ + /* c = rotlFixed((word32)c, 10U) */ \ + AS2( rol c, 10 ) \ + AS2( add a, e ) + + +// combine I into subround w/ setup +// esi already has c, setup for next round when done +// esp already has edi[index], setup for next round when done + +#define ASMSubroundI(a, b, c, d, e, index, s, k) \ + /* a += (c ^ (d & (b^c))) + data[i] + k */ \ + AS2( xor esi, b ) \ + AS2( and esi, d ) \ + AS2( add a, [edi + index * 4] ) \ + AS2( xor esi, c ) \ + AS2( lea a, [esi + a + k] ) \ + /* a = rotlFixed((word32)a, s) + e */ \ + AS2( mov esi, b ) \ + AS2( rol a, s ) \ + /* c = rotlFixed((word32)c, 10U) */ \ + AS2( rol c, 10 ) \ + AS2( add a, e ) + + +// combine J into subround w/ setup +// esi already has d, setup for next round when done +// esp already has edi[index], setup for next round when done + +#define ASMSubroundJ(a, b, c, d, e, index, s, k) \ + /* a += (b ^ (c | ~d))) + data[i] + k */ \ + AS1( not esi ) \ + AS2( or esi, c ) \ + /* c = rotlFixed((word32)c, 10U) */ \ + AS2( add a, [edi + index * 4] ) \ + AS2( xor esi, b ) \ + AS2( rol c, 10 ) \ + AS2( lea a, [esi + a + k] ) \ + /* a = rotlFixed((word32)a, s) + e */ \ + AS2( rol a, s ) \ + AS2( mov esi, c ) \ + AS2( add a, e ) + + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void RIPEMD160::AsmTransform(const byte* data, word32 times) +{ +#ifdef __GNUC__ + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + + #define PROLOG() \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + "push ebx;" \ + "push ebp;" + #define EPILOG() \ + "pop ebp;" \ + "pop ebx;" \ + "emms;" \ + ".att_syntax;" \ + : \ + : "c" (this), "D" (data), "d" (times) \ + : "%esi", "%eax", "memory", "cc" \ + ); + +#else + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + + #define PROLOG() \ + AS1( push ebp ) \ + AS2( mov ebp, esp ) \ + AS2( movd mm3, edi ) \ + AS2( movd mm4, ebx ) \ + AS2( movd mm5, esi ) \ + AS2( movd mm6, ebp ) \ + AS2( mov edi, DWORD PTR [ebp + 8] ) \ + AS2( mov edx, DWORD PTR [ebp + 12] ) + + #define EPILOG() \ + AS2( movd ebp, mm6 ) \ + AS2( movd esi, mm5 ) \ + AS2( movd ebx, mm4 ) \ + AS2( movd edi, mm3 ) \ + AS2( mov esp, ebp ) \ + AS1( pop ebp ) \ + AS1( emms ) \ + AS1( ret 8 ) + +#endif + + PROLOG() + + #ifdef OLD_GCC_OFFSET + AS2( lea esi, [ecx + 20] ) // digest_[0] + #else + AS2( lea esi, [ecx + 16] ) // digest_[0] + #endif + + AS2( sub esp, 24 ) // make room for tmp a1 - e1 + AS2( movd mm1, esi ) // store digest_ + +#ifdef _MSC_VER + AS1( loopStart: ) // loopStart +#else + AS1( 0: ) // loopStart for some gas (need numeric for jump back +#endif + + AS2( movd mm2, edx ) // store times_ + + AS2( mov eax, [esi] ) // a1 + AS2( mov ebx, [esi + 4] ) // b1 + AS2( mov ecx, [esi + 8] ) // c1 + AS2( mov edx, [esi + 12] ) // d1 + AS2( mov ebp, [esi + 16] ) // e1 + + // setup + AS2( mov esi, ecx ) + + ASMSubroundF( eax, ebx, ecx, edx, ebp, 0, 11) + ASMSubroundF( ebp, eax, ebx, ecx, edx, 1, 14) + ASMSubroundF( edx, ebp, eax, ebx, ecx, 2, 15) + ASMSubroundF( ecx, edx, ebp, eax, ebx, 3, 12) + ASMSubroundF( ebx, ecx, edx, ebp, eax, 4, 5) + ASMSubroundF( eax, ebx, ecx, edx, ebp, 5, 8) + ASMSubroundF( ebp, eax, ebx, ecx, edx, 6, 7) + ASMSubroundF( edx, ebp, eax, ebx, ecx, 7, 9) + ASMSubroundF( ecx, edx, ebp, eax, ebx, 8, 11) + ASMSubroundF( ebx, ecx, edx, ebp, eax, 9, 13) + ASMSubroundF( eax, ebx, ecx, edx, ebp, 10, 14) + ASMSubroundF( ebp, eax, ebx, ecx, edx, 11, 15) + ASMSubroundF( edx, ebp, eax, ebx, ecx, 12, 6) + ASMSubroundF( ecx, edx, ebp, eax, ebx, 13, 7) + ASMSubroundF( ebx, ecx, edx, ebp, eax, 14, 9) + ASMSubroundF( eax, ebx, ecx, edx, ebp, 15, 8) + + ASMSubroundG( ebp, eax, ebx, ecx, edx, 7, 7, k1) + ASMSubroundG( edx, ebp, eax, ebx, ecx, 4, 6, k1) + ASMSubroundG( ecx, edx, ebp, eax, ebx, 13, 8, k1) + ASMSubroundG( ebx, ecx, edx, ebp, eax, 1, 13, k1) + ASMSubroundG( eax, ebx, ecx, edx, ebp, 10, 11, k1) + ASMSubroundG( ebp, eax, ebx, ecx, edx, 6, 9, k1) + ASMSubroundG( edx, ebp, eax, ebx, ecx, 15, 7, k1) + ASMSubroundG( ecx, edx, ebp, eax, ebx, 3, 15, k1) + ASMSubroundG( ebx, ecx, edx, ebp, eax, 12, 7, k1) + ASMSubroundG( eax, ebx, ecx, edx, ebp, 0, 12, k1) + ASMSubroundG( ebp, eax, ebx, ecx, edx, 9, 15, k1) + ASMSubroundG( edx, ebp, eax, ebx, ecx, 5, 9, k1) + ASMSubroundG( ecx, edx, ebp, eax, ebx, 2, 11, k1) + ASMSubroundG( ebx, ecx, edx, ebp, eax, 14, 7, k1) + ASMSubroundG( eax, ebx, ecx, edx, ebp, 11, 13, k1) + ASMSubroundG( ebp, eax, ebx, ecx, edx, 8, 12, k1) + + ASMSubroundH( edx, ebp, eax, ebx, ecx, 3, 11, k2) + ASMSubroundH( ecx, edx, ebp, eax, ebx, 10, 13, k2) + ASMSubroundH( ebx, ecx, edx, ebp, eax, 14, 6, k2) + ASMSubroundH( eax, ebx, ecx, edx, ebp, 4, 7, k2) + ASMSubroundH( ebp, eax, ebx, ecx, edx, 9, 14, k2) + ASMSubroundH( edx, ebp, eax, ebx, ecx, 15, 9, k2) + ASMSubroundH( ecx, edx, ebp, eax, ebx, 8, 13, k2) + ASMSubroundH( ebx, ecx, edx, ebp, eax, 1, 15, k2) + ASMSubroundH( eax, ebx, ecx, edx, ebp, 2, 14, k2) + ASMSubroundH( ebp, eax, ebx, ecx, edx, 7, 8, k2) + ASMSubroundH( edx, ebp, eax, ebx, ecx, 0, 13, k2) + ASMSubroundH( ecx, edx, ebp, eax, ebx, 6, 6, k2) + ASMSubroundH( ebx, ecx, edx, ebp, eax, 13, 5, k2) + ASMSubroundH( eax, ebx, ecx, edx, ebp, 11, 12, k2) + ASMSubroundH( ebp, eax, ebx, ecx, edx, 5, 7, k2) + ASMSubroundH( edx, ebp, eax, ebx, ecx, 12, 5, k2) + + ASMSubroundI( ecx, edx, ebp, eax, ebx, 1, 11, k3) + ASMSubroundI( ebx, ecx, edx, ebp, eax, 9, 12, k3) + ASMSubroundI( eax, ebx, ecx, edx, ebp, 11, 14, k3) + ASMSubroundI( ebp, eax, ebx, ecx, edx, 10, 15, k3) + ASMSubroundI( edx, ebp, eax, ebx, ecx, 0, 14, k3) + ASMSubroundI( ecx, edx, ebp, eax, ebx, 8, 15, k3) + ASMSubroundI( ebx, ecx, edx, ebp, eax, 12, 9, k3) + ASMSubroundI( eax, ebx, ecx, edx, ebp, 4, 8, k3) + ASMSubroundI( ebp, eax, ebx, ecx, edx, 13, 9, k3) + ASMSubroundI( edx, ebp, eax, ebx, ecx, 3, 14, k3) + ASMSubroundI( ecx, edx, ebp, eax, ebx, 7, 5, k3) + ASMSubroundI( ebx, ecx, edx, ebp, eax, 15, 6, k3) + ASMSubroundI( eax, ebx, ecx, edx, ebp, 14, 8, k3) + ASMSubroundI( ebp, eax, ebx, ecx, edx, 5, 6, k3) + ASMSubroundI( edx, ebp, eax, ebx, ecx, 6, 5, k3) + ASMSubroundI( ecx, edx, ebp, eax, ebx, 2, 12, k3) + + // setup + AS2( mov esi, ebp ) + + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 4, 9, k4) + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 0, 15, k4) + ASMSubroundJ( ebp, eax, ebx, ecx, edx, 5, 5, k4) + ASMSubroundJ( edx, ebp, eax, ebx, ecx, 9, 11, k4) + ASMSubroundJ( ecx, edx, ebp, eax, ebx, 7, 6, k4) + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 12, 8, k4) + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 2, 13, k4) + ASMSubroundJ( ebp, eax, ebx, ecx, edx, 10, 12, k4) + ASMSubroundJ( edx, ebp, eax, ebx, ecx, 14, 5, k4) + ASMSubroundJ( ecx, edx, ebp, eax, ebx, 1, 12, k4) + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 3, 13, k4) + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 8, 14, k4) + ASMSubroundJ( ebp, eax, ebx, ecx, edx, 11, 11, k4) + ASMSubroundJ( edx, ebp, eax, ebx, ecx, 6, 8, k4) + ASMSubroundJ( ecx, edx, ebp, eax, ebx, 15, 5, k4) + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 13, 6, k4) + + // store a1 - e1 on stack + AS2( movd esi, mm1 ) // digest_ + + AS2( mov [esp], eax ) + AS2( mov [esp + 4], ebx ) + AS2( mov [esp + 8], ecx ) + AS2( mov [esp + 12], edx ) + AS2( mov [esp + 16], ebp ) + + AS2( mov eax, [esi] ) // a2 + AS2( mov ebx, [esi + 4] ) // b2 + AS2( mov ecx, [esi + 8] ) // c2 + AS2( mov edx, [esi + 12] ) // d2 + AS2( mov ebp, [esi + 16] ) // e2 + + + // setup + AS2( mov esi, edx ) + + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 5, 8, k5) + ASMSubroundJ( ebp, eax, ebx, ecx, edx, 14, 9, k5) + ASMSubroundJ( edx, ebp, eax, ebx, ecx, 7, 9, k5) + ASMSubroundJ( ecx, edx, ebp, eax, ebx, 0, 11, k5) + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 9, 13, k5) + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 2, 15, k5) + ASMSubroundJ( ebp, eax, ebx, ecx, edx, 11, 15, k5) + ASMSubroundJ( edx, ebp, eax, ebx, ecx, 4, 5, k5) + ASMSubroundJ( ecx, edx, ebp, eax, ebx, 13, 7, k5) + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 6, 7, k5) + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 15, 8, k5) + ASMSubroundJ( ebp, eax, ebx, ecx, edx, 8, 11, k5) + ASMSubroundJ( edx, ebp, eax, ebx, ecx, 1, 14, k5) + ASMSubroundJ( ecx, edx, ebp, eax, ebx, 10, 14, k5) + ASMSubroundJ( ebx, ecx, edx, ebp, eax, 3, 12, k5) + ASMSubroundJ( eax, ebx, ecx, edx, ebp, 12, 6, k5) + + // setup + AS2( mov esi, ebx ) + + ASMSubroundI( ebp, eax, ebx, ecx, edx, 6, 9, k6) + ASMSubroundI( edx, ebp, eax, ebx, ecx, 11, 13, k6) + ASMSubroundI( ecx, edx, ebp, eax, ebx, 3, 15, k6) + ASMSubroundI( ebx, ecx, edx, ebp, eax, 7, 7, k6) + ASMSubroundI( eax, ebx, ecx, edx, ebp, 0, 12, k6) + ASMSubroundI( ebp, eax, ebx, ecx, edx, 13, 8, k6) + ASMSubroundI( edx, ebp, eax, ebx, ecx, 5, 9, k6) + ASMSubroundI( ecx, edx, ebp, eax, ebx, 10, 11, k6) + ASMSubroundI( ebx, ecx, edx, ebp, eax, 14, 7, k6) + ASMSubroundI( eax, ebx, ecx, edx, ebp, 15, 7, k6) + ASMSubroundI( ebp, eax, ebx, ecx, edx, 8, 12, k6) + ASMSubroundI( edx, ebp, eax, ebx, ecx, 12, 7, k6) + ASMSubroundI( ecx, edx, ebp, eax, ebx, 4, 6, k6) + ASMSubroundI( ebx, ecx, edx, ebp, eax, 9, 15, k6) + ASMSubroundI( eax, ebx, ecx, edx, ebp, 1, 13, k6) + ASMSubroundI( ebp, eax, ebx, ecx, edx, 2, 11, k6) + + ASMSubroundH( edx, ebp, eax, ebx, ecx, 15, 9, k7) + ASMSubroundH( ecx, edx, ebp, eax, ebx, 5, 7, k7) + ASMSubroundH( ebx, ecx, edx, ebp, eax, 1, 15, k7) + ASMSubroundH( eax, ebx, ecx, edx, ebp, 3, 11, k7) + ASMSubroundH( ebp, eax, ebx, ecx, edx, 7, 8, k7) + ASMSubroundH( edx, ebp, eax, ebx, ecx, 14, 6, k7) + ASMSubroundH( ecx, edx, ebp, eax, ebx, 6, 6, k7) + ASMSubroundH( ebx, ecx, edx, ebp, eax, 9, 14, k7) + ASMSubroundH( eax, ebx, ecx, edx, ebp, 11, 12, k7) + ASMSubroundH( ebp, eax, ebx, ecx, edx, 8, 13, k7) + ASMSubroundH( edx, ebp, eax, ebx, ecx, 12, 5, k7) + ASMSubroundH( ecx, edx, ebp, eax, ebx, 2, 14, k7) + ASMSubroundH( ebx, ecx, edx, ebp, eax, 10, 13, k7) + ASMSubroundH( eax, ebx, ecx, edx, ebp, 0, 13, k7) + ASMSubroundH( ebp, eax, ebx, ecx, edx, 4, 7, k7) + ASMSubroundH( edx, ebp, eax, ebx, ecx, 13, 5, k7) + + ASMSubroundG( ecx, edx, ebp, eax, ebx, 8, 15, k8) + ASMSubroundG( ebx, ecx, edx, ebp, eax, 6, 5, k8) + ASMSubroundG( eax, ebx, ecx, edx, ebp, 4, 8, k8) + ASMSubroundG( ebp, eax, ebx, ecx, edx, 1, 11, k8) + ASMSubroundG( edx, ebp, eax, ebx, ecx, 3, 14, k8) + ASMSubroundG( ecx, edx, ebp, eax, ebx, 11, 14, k8) + ASMSubroundG( ebx, ecx, edx, ebp, eax, 15, 6, k8) + ASMSubroundG( eax, ebx, ecx, edx, ebp, 0, 14, k8) + ASMSubroundG( ebp, eax, ebx, ecx, edx, 5, 6, k8) + ASMSubroundG( edx, ebp, eax, ebx, ecx, 12, 9, k8) + ASMSubroundG( ecx, edx, ebp, eax, ebx, 2, 12, k8) + ASMSubroundG( ebx, ecx, edx, ebp, eax, 13, 9, k8) + ASMSubroundG( eax, ebx, ecx, edx, ebp, 9, 12, k8) + ASMSubroundG( ebp, eax, ebx, ecx, edx, 7, 5, k8) + ASMSubroundG( edx, ebp, eax, ebx, ecx, 10, 15, k8) + ASMSubroundG( ecx, edx, ebp, eax, ebx, 14, 8, k8) + + ASMSubroundF( ebx, ecx, edx, ebp, eax, 12, 8) + ASMSubroundF( eax, ebx, ecx, edx, ebp, 15, 5) + ASMSubroundF( ebp, eax, ebx, ecx, edx, 10, 12) + ASMSubroundF( edx, ebp, eax, ebx, ecx, 4, 9) + ASMSubroundF( ecx, edx, ebp, eax, ebx, 1, 12) + ASMSubroundF( ebx, ecx, edx, ebp, eax, 5, 5) + ASMSubroundF( eax, ebx, ecx, edx, ebp, 8, 14) + ASMSubroundF( ebp, eax, ebx, ecx, edx, 7, 6) + ASMSubroundF( edx, ebp, eax, ebx, ecx, 6, 8) + ASMSubroundF( ecx, edx, ebp, eax, ebx, 2, 13) + ASMSubroundF( ebx, ecx, edx, ebp, eax, 13, 6) + ASMSubroundF( eax, ebx, ecx, edx, ebp, 14, 5) + ASMSubroundF( ebp, eax, ebx, ecx, edx, 0, 15) + ASMSubroundF( edx, ebp, eax, ebx, ecx, 3, 13) + ASMSubroundF( ecx, edx, ebp, eax, ebx, 9, 11) + ASMSubroundF( ebx, ecx, edx, ebp, eax, 11, 11) + + // advance data and store for next round + AS2( add edi, 64 ) + AS2( movd esi, mm1 ) // digest_ + AS2( movd mm0, edi ) // store + + // now edi as tmp + + // c1 = digest_[1] + c1 + d2; + AS2( add [esp + 8], edx ) // + d2 + AS2( mov edi, [esi + 4] ) // digest_[1] + AS2( add [esp + 8], edi ) + + // digest_[1] = digest_[2] + d1 + e2; + AS2( mov [esi + 4], ebp ) // e2 + AS2( mov edi, [esp + 12] ) // d1 + AS2( add edi, [esi + 8] ) // digest_[2] + AS2( add [esi + 4], edi ) + + // digest_[2] = digest_[3] + e1 + a2; + AS2( mov [esi + 8], eax ) // a2 + AS2( mov edi, [esp + 16] ) // e1 + AS2( add edi, [esi + 12] ) // digest_[3] + AS2( add [esi + 8], edi ) + + // digest_[3] = digest_[4] + a1 + b2; + AS2( mov [esi + 12], ebx ) // b2 + AS2( mov edi, [esp] ) // a1 + AS2( add edi, [esi + 16] ) // digest_[4] + AS2( add [esi + 12], edi ) + + // digest_[4] = digest_[0] + b1 + c2; + AS2( mov [esi + 16], ecx ) // c2 + AS2( mov edi, [esp + 4] ) // b1 + AS2( add edi, [esi] ) // digest_[0] + AS2( add [esi + 16], edi ) + + // digest_[0] = c1; + AS2( mov edi, [esp + 8] ) // c1 + AS2( mov [esi], edi ) + + // setup for loop back + AS2( movd edx, mm2 ) // times + AS2( movd edi, mm0 ) // data, already advanced + AS1( dec edx ) +#ifdef _MSC_VER + AS1( jnz loopStart ) // loopStart +#else + AS1( jnz 0b ) // loopStart +#endif + + // inline adjust + AS2( add esp, 24 ) // fix room on stack + + EPILOG() +} + + +#endif // DO_RIPEMD_ASM + + +} // namespace TaoCrypt diff --git a/mysql/extra/yassl/taocrypt/src/rsa.cpp b/mysql/extra/yassl/taocrypt/src/rsa.cpp new file mode 100644 index 0000000..73f678e --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/rsa.cpp @@ -0,0 +1,215 @@ +/* + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's rsa.cpp from CryptoPP */ + +#include "runtime.hpp" +#include "rsa.hpp" +#include "asn.hpp" +#include "modarith.hpp" + + + +namespace TaoCrypt { + + +Integer RSA_PublicKey::ApplyFunction(const Integer& x) const +{ + return a_exp_b_mod_c(x, e_, n_); +} + + +RSA_PublicKey::RSA_PublicKey(Source& source) +{ + Initialize(source); +} + + +void RSA_PublicKey::Initialize(Source& source) +{ + RSA_Public_Decoder decoder(source); + decoder.Decode(*this); +} + + +Integer RSA_PrivateKey::CalculateInverse(RandomNumberGenerator& rng, + const Integer& x) const +{ + ModularArithmetic modn(n_); + + Integer r(rng, Integer::One(), n_ - Integer::One()); + Integer re = modn.Exponentiate(r, e_); + re = modn.Multiply(re, x); // blind + + // here we follow the notation of PKCS #1 and let u=q inverse mod p + // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q + + Integer y = ModularRoot(re, dq_, dp_, q_, p_, u_); + y = modn.Divide(y, r); // unblind + + return y; +} + + +RSA_PrivateKey::RSA_PrivateKey(Source& source) +{ + Initialize(source); +} + + +void RSA_PrivateKey::Initialize(Source& source) +{ + RSA_Private_Decoder decoder(source); + decoder.Decode(*this); +} + + +void RSA_BlockType2::Pad(const byte *input, word32 inputLen, byte *pkcsBlock, + word32 pkcsBlockLen, RandomNumberGenerator& rng) const +{ + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + pkcsBlock[0] = 0; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + pkcsBlock[0] = 2; // block type 2 + + // pad with non-zero random bytes + word32 padLen = pkcsBlockLen - inputLen - 1; + rng.GenerateBlock(&pkcsBlock[1], padLen); + for (word32 i = 1; i < padLen; i++) + if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator + memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); +} + +word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, + byte *output) const +{ + bool invalid = false; + unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U); + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + invalid = (pkcsBlock[0] != 0) || invalid; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + // Require block type 2. + invalid = (pkcsBlock[0] != 2) || invalid; + + // skip past the padding until we find the separator + unsigned i=1; + while (i maxOutputLen) || invalid; + + if (invalid) + return 0; + + memcpy (output, pkcsBlock+i, outputLen); + return outputLen; +} + + +void RSA_BlockType1::Pad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, RandomNumberGenerator&) const +{ + // sanity checks + if (input == NULL || pkcsBlock == NULL) + return; + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + pkcsBlock[0] = 0; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + pkcsBlock[0] = 1; // block type 1 for SSL + + // pad with 0xff bytes + memset(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator + memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); +} + + +word32 RSA_BlockType1::UnPad(const byte* pkcsBlock, word32 pkcsBlockLen, + byte* output) const +{ + bool invalid = false; + unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U); + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + invalid = (pkcsBlock[0] != 0) || invalid; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + // Require block type 1 for SSL. + invalid = (pkcsBlock[0] != 1) || invalid; + + // skip past the padding until we find the separator + unsigned i=1; + while (i maxOutputLen) || invalid; + + if (invalid) + return 0; + + memcpy(output, pkcsBlock+i, outputLen); + return outputLen; +} + + +word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain) +{ + PK_Lengths lengths(key.GetModulus()); + + ByteBlock paddedBlock(BitsToBytes(lengths.PaddedBlockBitLength())); + Integer x = key.ApplyFunction(Integer(sig, + lengths.FixedCiphertextLength())); + if (x.ByteCount() > paddedBlock.size()) + x = Integer::Zero(); + x.Encode(paddedBlock.get_buffer(), paddedBlock.size()); + return RSA_BlockType1().UnPad(paddedBlock.get_buffer(), + lengths.PaddedBlockBitLength(), plain); +} + + +} // namespace diff --git a/mysql/extra/yassl/taocrypt/src/sha.cpp b/mysql/extra/yassl/taocrypt/src/sha.cpp new file mode 100644 index 0000000..4206f7f --- /dev/null +++ b/mysql/extra/yassl/taocrypt/src/sha.cpp @@ -0,0 +1,1033 @@ +/* + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* based on Wei Dai's sha.cpp from CryptoPP */ + +#include "runtime.hpp" +#include +#include "sha.hpp" +#ifdef USE_SYS_STL + #include +#else + #include "algorithm.hpp" +#endif + + +namespace STL = STL_NAMESPACE; + + + +namespace TaoCrypt { + +#define blk0(i) (W[i] = buffer_[i]) +#define blk1(i) (W[i&15] = \ + rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) + +#define f1(x,y,z) (z^(x &(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) + +// (R0+R1), R2, R3, R4 are the different operations used in SHA1 +#define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \ + rotlFixed(v,5); w = rotlFixed(w,30); +#define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \ + rotlFixed(v,5); w = rotlFixed(w,30); +#define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \ + rotlFixed(v,5); w = rotlFixed(w,30); +#define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \ + rotlFixed(v,5); w = rotlFixed(w,30); +#define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \ + rotlFixed(v,5); w = rotlFixed(w,30); + + +void SHA::Init() +{ + digest_[0] = 0x67452301L; + digest_[1] = 0xEFCDAB89L; + digest_[2] = 0x98BADCFEL; + digest_[3] = 0x10325476L; + digest_[4] = 0xC3D2E1F0L; + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + +void SHA256::Init() +{ + digest_[0] = 0x6A09E667L; + digest_[1] = 0xBB67AE85L; + digest_[2] = 0x3C6EF372L; + digest_[3] = 0xA54FF53AL; + digest_[4] = 0x510E527FL; + digest_[5] = 0x9B05688CL; + digest_[6] = 0x1F83D9ABL; + digest_[7] = 0x5BE0CD19L; + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + + +void SHA224::Init() +{ + digest_[0] = 0xc1059ed8; + digest_[1] = 0x367cd507; + digest_[2] = 0x3070dd17; + digest_[3] = 0xf70e5939; + digest_[4] = 0xffc00b31; + digest_[5] = 0x68581511; + digest_[6] = 0x64f98fa7; + digest_[7] = 0xbefa4fa4; + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + + +#ifdef WORD64_AVAILABLE + +void SHA512::Init() +{ + digest_[0] = W64LIT(0x6a09e667f3bcc908); + digest_[1] = W64LIT(0xbb67ae8584caa73b); + digest_[2] = W64LIT(0x3c6ef372fe94f82b); + digest_[3] = W64LIT(0xa54ff53a5f1d36f1); + digest_[4] = W64LIT(0x510e527fade682d1); + digest_[5] = W64LIT(0x9b05688c2b3e6c1f); + digest_[6] = W64LIT(0x1f83d9abfb41bd6b); + digest_[7] = W64LIT(0x5be0cd19137e2179); + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + + +void SHA384::Init() +{ + digest_[0] = W64LIT(0xcbbb9d5dc1059ed8); + digest_[1] = W64LIT(0x629a292a367cd507); + digest_[2] = W64LIT(0x9159015a3070dd17); + digest_[3] = W64LIT(0x152fecd8f70e5939); + digest_[4] = W64LIT(0x67332667ffc00b31); + digest_[5] = W64LIT(0x8eb44a8768581511); + digest_[6] = W64LIT(0xdb0c2e0d64f98fa7); + digest_[7] = W64LIT(0x47b5481dbefa4fa4); + + buffLen_ = 0; + loLen_ = 0; + hiLen_ = 0; +} + +#endif // WORD64_AVAILABLE + + +SHA::SHA(const SHA& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32), + BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + + +SHA256::SHA256(const SHA256& that) : HASHwithTransform(DIGEST_SIZE / + sizeof(word32), BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + + +SHA224::SHA224(const SHA224& that) : HASHwithTransform(SHA256::DIGEST_SIZE / + sizeof(word32), BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + + +#ifdef WORD64_AVAILABLE + +SHA512::SHA512(const SHA512& that) : HASH64withTransform(DIGEST_SIZE / + sizeof(word64), BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + + +SHA384::SHA384(const SHA384& that) : HASH64withTransform(SHA512::DIGEST_SIZE / + sizeof(word64), BLOCK_SIZE) +{ + buffLen_ = that.buffLen_; + loLen_ = that.loLen_; + hiLen_ = that.hiLen_; + + memcpy(digest_, that.digest_, DIGEST_SIZE); + memcpy(buffer_, that.buffer_, BLOCK_SIZE); +} + +#endif // WORD64_AVAILABLE + + +SHA& SHA::operator= (const SHA& that) +{ + SHA tmp(that); + Swap(tmp); + + return *this; +} + + +SHA256& SHA256::operator= (const SHA256& that) +{ + SHA256 tmp(that); + Swap(tmp); + + return *this; +} + + +SHA224& SHA224::operator= (const SHA224& that) +{ + SHA224 tmp(that); + Swap(tmp); + + return *this; +} + + +#ifdef WORD64_AVAILABLE + +SHA512& SHA512::operator= (const SHA512& that) +{ + SHA512 tmp(that); + Swap(tmp); + + return *this; +} + + +SHA384& SHA384::operator= (const SHA384& that) +{ + SHA384 tmp(that); + Swap(tmp); + + return *this; +} + +#endif // WORD64_AVAILABLE + + +void SHA::Swap(SHA& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +void SHA256::Swap(SHA256& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +void SHA224::Swap(SHA224& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +#ifdef WORD64_AVAILABLE + +void SHA512::Swap(SHA512& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + + +void SHA384::Swap(SHA384& other) +{ + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); + + memcpy(digest_, other.digest_, DIGEST_SIZE); + memcpy(buffer_, other.buffer_, BLOCK_SIZE); +} + +#endif // WORD64_AVIALABLE + + +#ifdef DO_SHA_ASM + +// Update digest with data of size len +void SHA::Update(const byte* data, word32 len) +{ + if (!isMMX) { + HASHwithTransform::Update(data, len); + return; + } + + byte* local = reinterpret_cast(buffer_); + + // remove buffered data if possible + if (buffLen_) { + word32 add = min(len, BLOCK_SIZE - buffLen_); + memcpy(&local[buffLen_], data, add); + + buffLen_ += add; + data += add; + len -= add; + + if (buffLen_ == BLOCK_SIZE) { + ByteReverse(local, local, BLOCK_SIZE); + Transform(); + AddLength(BLOCK_SIZE); + buffLen_ = 0; + } + } + + // all at once for asm + if (buffLen_ == 0) { + word32 times = len / BLOCK_SIZE; + if (times) { + AsmTransform(data, times); + const word32 add = BLOCK_SIZE * times; + AddLength(add); + len -= add; + data += add; + } + } + + // cache any data left + if (len) { + memcpy(&local[buffLen_], data, len); + buffLen_ += len; + } +} + +#endif // DO_SHA_ASM + + +void SHA::Transform() +{ + word32 W[BLOCK_SIZE / sizeof(word32)]; + + // Copy context->state[] to working vars + word32 a = digest_[0]; + word32 b = digest_[1]; + word32 c = digest_[2]; + word32 d = digest_[3]; + word32 e = digest_[4]; + + // 4 rounds of 20 operations each. Loop unrolled. + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + // Add the working vars back into digest state[] + digest_[0] += a; + digest_[1] += b; + digest_[2] += c; + digest_[3] += d; + digest_[4] += e; + + // Wipe variables + a = b = c = d = e = 0; + memset(W, 0, sizeof(W)); +} + + +#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +#define a(i) T[(0-i)&7] +#define b(i) T[(1-i)&7] +#define c(i) T[(2-i)&7] +#define d(i) T[(3-i)&7] +#define e(i) T[(4-i)&7] +#define f(i) T[(5-i)&7] +#define g(i) T[(6-i)&7] +#define h(i) T[(7-i)&7] + +#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\ + d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) + +// for SHA256 +#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22)) +#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25)) +#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3)) +#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10)) + + +static const word32 K256[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 Transform256(word32* digest_, word32* buffer_) +{ + const word32* K = K256; + + word32 W[16]; + word32 T[8]; + + // Copy digest to working vars + memcpy(T, digest_, sizeof(T)); + + // 64 operations, partially loop unrolled + for (unsigned int j = 0; j < 64; j += 16) { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + + // Add the working vars back into digest + digest_[0] += a(0); + digest_[1] += b(0); + digest_[2] += c(0); + digest_[3] += d(0); + digest_[4] += e(0); + digest_[5] += f(0); + digest_[6] += g(0); + digest_[7] += h(0); + + // Wipe variables + memset(W, 0, sizeof(W)); + memset(T, 0, sizeof(T)); +} + + +// undef for 256 +#undef S0 +#undef S1 +#undef s0 +#undef s1 + + +void SHA256::Transform() +{ + Transform256(digest_, buffer_); +} + + +void SHA224::Transform() +{ + Transform256(digest_, buffer_); +} + + +#ifdef WORD64_AVAILABLE + +static const word64 K512[80] = { + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) +}; + + +// for SHA512 +#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39)) +#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41)) +#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7)) +#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6)) + + +static void Transform512(word64* digest_, word64* buffer_) +{ + const word64* K = K512; + + word64 W[16]; + word64 T[8]; + + // Copy digest to working vars + memcpy(T, digest_, sizeof(T)); + + // 64 operations, partially loop unrolled + for (unsigned int j = 0; j < 80; j += 16) { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + + // Add the working vars back into digest + + digest_[0] += a(0); + digest_[1] += b(0); + digest_[2] += c(0); + digest_[3] += d(0); + digest_[4] += e(0); + digest_[5] += f(0); + digest_[6] += g(0); + digest_[7] += h(0); + + // Wipe variables + memset(W, 0, sizeof(W)); + memset(T, 0, sizeof(T)); +} + + +void SHA512::Transform() +{ + Transform512(digest_, buffer_); +} + + +void SHA384::Transform() +{ + Transform512(digest_, buffer_); +} + +#endif // WORD64_AVIALABLE + + +#ifdef DO_SHA_ASM + +// f1(x,y,z) (z^(x &(y^z))) +// place in esi +#define ASMf1(x,y,z) \ + AS2( mov esi, y ) \ + AS2( xor esi, z ) \ + AS2( and esi, x ) \ + AS2( xor esi, z ) + + +// R0(v,w,x,y,z,i) = +// z+= f1(w,x,y) + W[i] + 0x5A827999 + rotlFixed(v,5); +// w = rotlFixed(w,30); + +// use esi for f +// use edi as tmp + + +#define ASMR0(v,w,x,y,z,i) \ + AS2( mov esi, x ) \ + AS2( mov edi, [esp + i * 4] ) \ + AS2( xor esi, y ) \ + AS2( and esi, w ) \ + AS2( lea z, [edi + z + 0x5A827999] ) \ + AS2( mov edi, v ) \ + AS2( xor esi, y ) \ + AS2( rol edi, 5 ) \ + AS2( add z, esi ) \ + AS2( rol w, 30 ) \ + AS2( add z, edi ) + + +/* Some macro stuff, but older gas ( < 2,16 ) can't process &, so do by hand + % won't work on gas at all + +#define xstr(s) str(s) +#define str(s) #s + +#define WOFF1(a) ( a & 15) +#define WOFF2(a) ((a + 2) & 15) +#define WOFF3(a) ((a + 8) & 15) +#define WOFF4(a) ((a + 13) & 15) + +#ifdef __GNUC__ + #define WGET1(i) asm("mov esp, [edi - "xstr(WOFF1(i))" * 4] "); + #define WGET2(i) asm("xor esp, [edi - "xstr(WOFF2(i))" * 4] "); + #define WGET3(i) asm("xor esp, [edi - "xstr(WOFF3(i))" * 4] "); + #define WGET4(i) asm("xor esp, [edi - "xstr(WOFF4(i))" * 4] "); + #define WPUT1(i) asm("mov [edi - "xstr(WOFF1(i))" * 4], esp "); +#else + #define WGET1(i) AS2( mov esp, [edi - WOFF1(i) * 4] ) + #define WGET2(i) AS2( xor esp, [edi - WOFF2(i) * 4] ) + #define WGET3(i) AS2( xor esp, [edi - WOFF3(i) * 4] ) + #define WGET4(i) AS2( xor esp, [edi - WOFF4(i) * 4] ) + #define WPUT1(i) AS2( mov [edi - WOFF1(i) * 4], esp ) +#endif +*/ + +// ASMR1 = ASMR0 but use esp for W calcs + +#define ASMR1(v,w,x,y,z,i,W1,W2,W3,W4) \ + AS2( mov edi, [esp + W1 * 4] ) \ + AS2( mov esi, x ) \ + AS2( xor edi, [esp + W2 * 4] ) \ + AS2( xor esi, y ) \ + AS2( xor edi, [esp + W3 * 4] ) \ + AS2( and esi, w ) \ + AS2( xor edi, [esp + W4 * 4] ) \ + AS2( rol edi, 1 ) \ + AS2( xor esi, y ) \ + AS2( mov [esp + W1 * 4], edi ) \ + AS2( lea z, [edi + z + 0x5A827999] ) \ + AS2( mov edi, v ) \ + AS2( rol edi, 5 ) \ + AS2( add z, esi ) \ + AS2( rol w, 30 ) \ + AS2( add z, edi ) + + +// ASMR2 = ASMR1 but f is xor, xor instead + +#define ASMR2(v,w,x,y,z,i,W1,W2,W3,W4) \ + AS2( mov edi, [esp + W1 * 4] ) \ + AS2( mov esi, x ) \ + AS2( xor edi, [esp + W2 * 4] ) \ + AS2( xor esi, y ) \ + AS2( xor edi, [esp + W3 * 4] ) \ + AS2( xor esi, w ) \ + AS2( xor edi, [esp + W4 * 4] ) \ + AS2( rol edi, 1 ) \ + AS2( add z, esi ) \ + AS2( mov [esp + W1 * 4], edi ) \ + AS2( lea z, [edi + z + 0x6ED9EBA1] ) \ + AS2( mov edi, v ) \ + AS2( rol edi, 5 ) \ + AS2( rol w, 30 ) \ + AS2( add z, edi ) + + +// ASMR3 = ASMR2 but f is (x&y)|(z&(x|y)) +// which is (w&x)|(y&(w|x)) + +#define ASMR3(v,w,x,y,z,i,W1,W2,W3,W4) \ + AS2( mov edi, [esp + W1 * 4] ) \ + AS2( mov esi, x ) \ + AS2( xor edi, [esp + W2 * 4] ) \ + AS2( or esi, w ) \ + AS2( xor edi, [esp + W3 * 4] ) \ + AS2( and esi, y ) \ + AS2( xor edi, [esp + W4 * 4] ) \ + AS2( movd mm0, esi ) \ + AS2( rol edi, 1 ) \ + AS2( mov esi, x ) \ + AS2( mov [esp + W1 * 4], edi ) \ + AS2( and esi, w ) \ + AS2( lea z, [edi + z + 0x8F1BBCDC] ) \ + AS2( movd edi, mm0 ) \ + AS2( or esi, edi ) \ + AS2( mov edi, v ) \ + AS2( rol edi, 5 ) \ + AS2( add z, esi ) \ + AS2( rol w, 30 ) \ + AS2( add z, edi ) + + +// ASMR4 = ASMR2 but different constant + +#define ASMR4(v,w,x,y,z,i,W1,W2,W3,W4) \ + AS2( mov edi, [esp + W1 * 4] ) \ + AS2( mov esi, x ) \ + AS2( xor edi, [esp + W2 * 4] ) \ + AS2( xor esi, y ) \ + AS2( xor edi, [esp + W3 * 4] ) \ + AS2( xor esi, w ) \ + AS2( xor edi, [esp + W4 * 4] ) \ + AS2( rol edi, 1 ) \ + AS2( add z, esi ) \ + AS2( mov [esp + W1 * 4], edi ) \ + AS2( lea z, [edi + z + 0xCA62C1D6] ) \ + AS2( mov edi, v ) \ + AS2( rol edi, 5 ) \ + AS2( rol w, 30 ) \ + AS2( add z, edi ) + + +#ifdef _MSC_VER + __declspec(naked) +#else + __attribute__ ((noinline)) +#endif +void SHA::AsmTransform(const byte* data, word32 times) +{ +#ifdef __GNUC__ + #define AS1(x) #x ";" + #define AS2(x, y) #x ", " #y ";" + + #define PROLOG() \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + "push ebx;" \ + "push ebp;" + #define EPILOG() \ + "pop ebp;" \ + "pop ebx;" \ + "emms;" \ + ".att_syntax;" \ + : \ + : "c" (this), "D" (data), "a" (times) \ + : "%esi", "%edx", "memory", "cc" \ + ); + +#else + #define AS1(x) __asm x + #define AS2(x, y) __asm x, y + + #define PROLOG() \ + AS1( push ebp ) \ + AS2( mov ebp, esp ) \ + AS2( movd mm3, edi ) \ + AS2( movd mm4, ebx ) \ + AS2( movd mm5, esi ) \ + AS2( movd mm6, ebp ) \ + AS2( mov edi, data ) \ + AS2( mov eax, times ) + + #define EPILOG() \ + AS2( movd ebp, mm6 ) \ + AS2( movd esi, mm5 ) \ + AS2( movd ebx, mm4 ) \ + AS2( movd edi, mm3 ) \ + AS2( mov esp, ebp ) \ + AS1( pop ebp ) \ + AS1( emms ) \ + AS1( ret 8 ) +#endif + + PROLOG() + + AS2( mov esi, ecx ) + + #ifdef OLD_GCC_OFFSET + AS2( add esi, 20 ) // digest_[0] + #else + AS2( add esi, 16 ) // digest_[0] + #endif + + AS2( movd mm2, eax ) // store times_ + AS2( movd mm1, esi ) // store digest_ + + AS2( sub esp, 68 ) // make room on stack + +#ifdef _MSC_VER + AS1( loopStart: ) // loopStart +#else + AS1( 0: ) // loopStart for some gas (need numeric for jump back +#endif + + // byte reverse 16 words of input, 4 at a time, put on stack for W[] + + // part 1 + AS2( mov eax, [edi] ) + AS2( mov ebx, [edi + 4] ) + AS2( mov ecx, [edi + 8] ) + AS2( mov edx, [edi + 12] ) + + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( mov [esp], eax ) + AS2( mov [esp + 4], ebx ) + AS2( mov [esp + 8], ecx ) + AS2( mov [esp + 12], edx ) + + // part 2 + AS2( mov eax, [edi + 16] ) + AS2( mov ebx, [edi + 20] ) + AS2( mov ecx, [edi + 24] ) + AS2( mov edx, [edi + 28] ) + + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( mov [esp + 16], eax ) + AS2( mov [esp + 20], ebx ) + AS2( mov [esp + 24], ecx ) + AS2( mov [esp + 28], edx ) + + + // part 3 + AS2( mov eax, [edi + 32] ) + AS2( mov ebx, [edi + 36] ) + AS2( mov ecx, [edi + 40] ) + AS2( mov edx, [edi + 44] ) + + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( mov [esp + 32], eax ) + AS2( mov [esp + 36], ebx ) + AS2( mov [esp + 40], ecx ) + AS2( mov [esp + 44], edx ) + + + // part 4 + AS2( mov eax, [edi + 48] ) + AS2( mov ebx, [edi + 52] ) + AS2( mov ecx, [edi + 56] ) + AS2( mov edx, [edi + 60] ) + + AS1( bswap eax ) + AS1( bswap ebx ) + AS1( bswap ecx ) + AS1( bswap edx ) + + AS2( mov [esp + 48], eax ) + AS2( mov [esp + 52], ebx ) + AS2( mov [esp + 56], ecx ) + AS2( mov [esp + 60], edx ) + + AS2( mov [esp + 64], edi ) // store edi for end + + // read from digest_ + AS2( mov eax, [esi] ) // a1 + AS2( mov ebx, [esi + 4] ) // b1 + AS2( mov ecx, [esi + 8] ) // c1 + AS2( mov edx, [esi + 12] ) // d1 + AS2( mov ebp, [esi + 16] ) // e1 + + + ASMR0(eax, ebx, ecx, edx, ebp, 0) + ASMR0(ebp, eax, ebx, ecx, edx, 1) + ASMR0(edx, ebp, eax, ebx, ecx, 2) + ASMR0(ecx, edx, ebp, eax, ebx, 3) + ASMR0(ebx, ecx, edx, ebp, eax, 4) + ASMR0(eax, ebx, ecx, edx, ebp, 5) + ASMR0(ebp, eax, ebx, ecx, edx, 6) + ASMR0(edx, ebp, eax, ebx, ecx, 7) + ASMR0(ecx, edx, ebp, eax, ebx, 8) + ASMR0(ebx, ecx, edx, ebp, eax, 9) + ASMR0(eax, ebx, ecx, edx, ebp, 10) + ASMR0(ebp, eax, ebx, ecx, edx, 11) + ASMR0(edx, ebp, eax, ebx, ecx, 12) + ASMR0(ecx, edx, ebp, eax, ebx, 13) + ASMR0(ebx, ecx, edx, ebp, eax, 14) + ASMR0(eax, ebx, ecx, edx, ebp, 15) + + ASMR1(ebp, eax, ebx, ecx, edx, 16, 0, 2, 8, 13) + ASMR1(edx, ebp, eax, ebx, ecx, 17, 1, 3, 9, 14) + ASMR1(ecx, edx, ebp, eax, ebx, 18, 2, 4, 10, 15) + ASMR1(ebx, ecx, edx, ebp, eax, 19, 3, 5, 11, 0) + + ASMR2(eax, ebx, ecx, edx, ebp, 20, 4, 6, 12, 1) + ASMR2(ebp, eax, ebx, ecx, edx, 21, 5, 7, 13, 2) + ASMR2(edx, ebp, eax, ebx, ecx, 22, 6, 8, 14, 3) + ASMR2(ecx, edx, ebp, eax, ebx, 23, 7, 9, 15, 4) + ASMR2(ebx, ecx, edx, ebp, eax, 24, 8, 10, 0, 5) + ASMR2(eax, ebx, ecx, edx, ebp, 25, 9, 11, 1, 6) + ASMR2(ebp, eax, ebx, ecx, edx, 26, 10, 12, 2, 7) + ASMR2(edx, ebp, eax, ebx, ecx, 27, 11, 13, 3, 8) + ASMR2(ecx, edx, ebp, eax, ebx, 28, 12, 14, 4, 9) + ASMR2(ebx, ecx, edx, ebp, eax, 29, 13, 15, 5, 10) + ASMR2(eax, ebx, ecx, edx, ebp, 30, 14, 0, 6, 11) + ASMR2(ebp, eax, ebx, ecx, edx, 31, 15, 1, 7, 12) + ASMR2(edx, ebp, eax, ebx, ecx, 32, 0, 2, 8, 13) + ASMR2(ecx, edx, ebp, eax, ebx, 33, 1, 3, 9, 14) + ASMR2(ebx, ecx, edx, ebp, eax, 34, 2, 4, 10, 15) + ASMR2(eax, ebx, ecx, edx, ebp, 35, 3, 5, 11, 0) + ASMR2(ebp, eax, ebx, ecx, edx, 36, 4, 6, 12, 1) + ASMR2(edx, ebp, eax, ebx, ecx, 37, 5, 7, 13, 2) + ASMR2(ecx, edx, ebp, eax, ebx, 38, 6, 8, 14, 3) + ASMR2(ebx, ecx, edx, ebp, eax, 39, 7, 9, 15, 4) + + + ASMR3(eax, ebx, ecx, edx, ebp, 40, 8, 10, 0, 5) + ASMR3(ebp, eax, ebx, ecx, edx, 41, 9, 11, 1, 6) + ASMR3(edx, ebp, eax, ebx, ecx, 42, 10, 12, 2, 7) + ASMR3(ecx, edx, ebp, eax, ebx, 43, 11, 13, 3, 8) + ASMR3(ebx, ecx, edx, ebp, eax, 44, 12, 14, 4, 9) + ASMR3(eax, ebx, ecx, edx, ebp, 45, 13, 15, 5, 10) + ASMR3(ebp, eax, ebx, ecx, edx, 46, 14, 0, 6, 11) + ASMR3(edx, ebp, eax, ebx, ecx, 47, 15, 1, 7, 12) + ASMR3(ecx, edx, ebp, eax, ebx, 48, 0, 2, 8, 13) + ASMR3(ebx, ecx, edx, ebp, eax, 49, 1, 3, 9, 14) + ASMR3(eax, ebx, ecx, edx, ebp, 50, 2, 4, 10, 15) + ASMR3(ebp, eax, ebx, ecx, edx, 51, 3, 5, 11, 0) + ASMR3(edx, ebp, eax, ebx, ecx, 52, 4, 6, 12, 1) + ASMR3(ecx, edx, ebp, eax, ebx, 53, 5, 7, 13, 2) + ASMR3(ebx, ecx, edx, ebp, eax, 54, 6, 8, 14, 3) + ASMR3(eax, ebx, ecx, edx, ebp, 55, 7, 9, 15, 4) + ASMR3(ebp, eax, ebx, ecx, edx, 56, 8, 10, 0, 5) + ASMR3(edx, ebp, eax, ebx, ecx, 57, 9, 11, 1, 6) + ASMR3(ecx, edx, ebp, eax, ebx, 58, 10, 12, 2, 7) + ASMR3(ebx, ecx, edx, ebp, eax, 59, 11, 13, 3, 8) + + ASMR4(eax, ebx, ecx, edx, ebp, 60, 12, 14, 4, 9) + ASMR4(ebp, eax, ebx, ecx, edx, 61, 13, 15, 5, 10) + ASMR4(edx, ebp, eax, ebx, ecx, 62, 14, 0, 6, 11) + ASMR4(ecx, edx, ebp, eax, ebx, 63, 15, 1, 7, 12) + ASMR4(ebx, ecx, edx, ebp, eax, 64, 0, 2, 8, 13) + ASMR4(eax, ebx, ecx, edx, ebp, 65, 1, 3, 9, 14) + ASMR4(ebp, eax, ebx, ecx, edx, 66, 2, 4, 10, 15) + ASMR4(edx, ebp, eax, ebx, ecx, 67, 3, 5, 11, 0) + ASMR4(ecx, edx, ebp, eax, ebx, 68, 4, 6, 12, 1) + ASMR4(ebx, ecx, edx, ebp, eax, 69, 5, 7, 13, 2) + ASMR4(eax, ebx, ecx, edx, ebp, 70, 6, 8, 14, 3) + ASMR4(ebp, eax, ebx, ecx, edx, 71, 7, 9, 15, 4) + ASMR4(edx, ebp, eax, ebx, ecx, 72, 8, 10, 0, 5) + ASMR4(ecx, edx, ebp, eax, ebx, 73, 9, 11, 1, 6) + ASMR4(ebx, ecx, edx, ebp, eax, 74, 10, 12, 2, 7) + ASMR4(eax, ebx, ecx, edx, ebp, 75, 11, 13, 3, 8) + ASMR4(ebp, eax, ebx, ecx, edx, 76, 12, 14, 4, 9) + ASMR4(edx, ebp, eax, ebx, ecx, 77, 13, 15, 5, 10) + ASMR4(ecx, edx, ebp, eax, ebx, 78, 14, 0, 6, 11) + ASMR4(ebx, ecx, edx, ebp, eax, 79, 15, 1, 7, 12) + + + AS2( movd esi, mm1 ) // digest_ + + AS2( add [esi], eax ) // write out + AS2( add [esi + 4], ebx ) + AS2( add [esi + 8], ecx ) + AS2( add [esi + 12], edx ) + AS2( add [esi + 16], ebp ) + + // setup next round + AS2( movd ebp, mm2 ) // times + + AS2( mov edi, DWORD PTR [esp + 64] ) // data + + AS2( add edi, 64 ) // next round of data + AS2( mov [esp + 64], edi ) // restore + + AS1( dec ebp ) + AS2( movd mm2, ebp ) +#ifdef _MSC_VER + AS1( jnz loopStart ) // loopStart +#else + AS1( jnz 0b ) // loopStart +#endif + + // inline adjust + AS2( add esp, 68 ) // fix room on stack + + EPILOG() +} + + +#endif // DO_SHA_ASM + +} // namespace -- cgit v1.1