maxep 6 роки тому
коміт
ae0a6de15d
100 змінених файлів з 19960 додано та 0 видалено
  1. 5 0
      .gitignore
  2. 674 0
      LICENSE
  3. 97 0
      Package.swift
  4. 3 0
      README.md
  5. 314 0
      Sources/Argon2/LICENSE
  6. 452 0
      Sources/Argon2/argon2.c
  7. 390 0
      Sources/Argon2/blake2b.c
  8. 648 0
      Sources/Argon2/core.c
  9. 463 0
      Sources/Argon2/encoding.c
  10. 437 0
      Sources/Argon2/include/argon2.h
  11. 156 0
      Sources/Argon2/include/blake2/blake2-impl.h
  12. 89 0
      Sources/Argon2/include/blake2/blake2.h
  13. 471 0
      Sources/Argon2/include/blake2/blamka-round-opt.h
  14. 56 0
      Sources/Argon2/include/blake2/blamka-round-ref.h
  15. 228 0
      Sources/Argon2/include/core.h
  16. 57 0
      Sources/Argon2/include/encoding.h
  17. 4 0
      Sources/Argon2/include/module.modulemap
  18. 67 0
      Sources/Argon2/include/thread.h
  19. 194 0
      Sources/Argon2/ref.c
  20. 57 0
      Sources/Argon2/thread.c
  21. 234 0
      Sources/Binary/Bytes.swift
  22. 181 0
      Sources/Binary/BytesRepresentable.swift
  23. 24 0
      Sources/Binary/Error.swift
  24. 74 0
      Sources/Binary/Input.swift
  25. 57 0
      Sources/Binary/Output.swift
  26. 188 0
      Sources/Binary/Streamable.swift
  27. 68 0
      Sources/Binary/TLV.swift
  28. 137 0
      Sources/Crypto/AES.swift
  29. 60 0
      Sources/Crypto/Argon2.swift
  30. 56 0
      Sources/Crypto/ChaCha20.swift
  31. 27 0
      Sources/Crypto/Cipher.swift
  32. 30 0
      Sources/Crypto/Error.swift
  33. 111 0
      Sources/Crypto/Hash.swift
  34. 25 0
      Sources/Crypto/KeyDerivation.swift
  35. 56 0
      Sources/Crypto/Salsa20.swift
  36. 59 0
      Sources/Crypto/Twofish.swift
  37. 290 0
      Sources/Gzip/Gzip.swift
  38. 21 0
      Sources/Gzip/LICENSE
  39. 50 0
      Sources/KDB/CompositeKey.swift
  40. 124 0
      Sources/KDB/Database.swift
  41. 76 0
      Sources/KDB/Date.swift
  42. 78 0
      Sources/KDB/Entry.swift
  43. 28 0
      Sources/KDB/Error.swift
  44. 51 0
      Sources/KDB/Group.swift
  45. 83 0
      Sources/KDB/Header.swift
  46. 93 0
      Sources/KDB/Row.swift
  47. 41 0
      Sources/KDBX/Cipher.swift
  48. 53 0
      Sources/KDBX/CompositeKey.swift
  49. 25 0
      Sources/KDBX/Database.swift
  50. 108 0
      Sources/KDBX/Database3.swift
  51. 93 0
      Sources/KDBX/Database4.swift
  52. 30 0
      Sources/KDBX/Error.swift
  53. 88 0
      Sources/KDBX/File.swift
  54. 119 0
      Sources/KDBX/Header.swift
  55. 70 0
      Sources/KDBX/KeyDerivation.swift
  56. 283 0
      Sources/KDBX/Variant.swift
  57. 3 0
      Sources/KeePass/KeePass.swift
  58. 18 0
      Sources/Sodium/LICENSE
  59. 1079 0
      Sources/Sodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
  60. 400 0
      Sources/Sodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c
  61. 262 0
      Sources/Sodium/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c
  62. 41 0
      Sources/Sodium/crypto_auth/crypto_auth.c
  63. 118 0
      Sources/Sodium/crypto_auth/hmacsha256/auth_hmacsha256.c
  64. 118 0
      Sources/Sodium/crypto_auth/hmacsha512/auth_hmacsha512.c
  65. 93 0
      Sources/Sodium/crypto_auth/hmacsha512256/auth_hmacsha512256.c
  66. 114 0
      Sources/Sodium/crypto_box/crypto_box.c
  67. 115 0
      Sources/Sodium/crypto_box/crypto_box_easy.c
  68. 68 0
      Sources/Sodium/crypto_box/crypto_box_seal.c
  69. 204 0
      Sources/Sodium/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c
  70. 79 0
      Sources/Sodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c
  71. 156 0
      Sources/Sodium/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c
  72. 225 0
      Sources/Sodium/crypto_core/ed25519/core_ed25519.c
  73. 156 0
      Sources/Sodium/crypto_core/ed25519/core_ristretto255.c
  74. 2866 0
      Sources/Sodium/crypto_core/ed25519/ref10/ed25519_ref10.c
  75. 1344 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/base.h
  76. 40 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/base2.h
  77. 40 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/constants.h
  78. 220 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/fe.h
  79. 1344 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_51/base.h
  80. 40 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_51/base2.h
  81. 41 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_51/constants.h
  82. 116 0
      Sources/Sodium/crypto_core/ed25519/ref10/fe_51/fe.h
  83. 93 0
      Sources/Sodium/crypto_core/hchacha20/core_hchacha20.c
  84. 21 0
      Sources/Sodium/crypto_core/hsalsa20/core_hsalsa20.c
  85. 95 0
      Sources/Sodium/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c
  86. 195 0
      Sources/Sodium/crypto_core/salsa/ref/core_salsa_ref.c
  87. 55 0
      Sources/Sodium/crypto_generichash/blake2b/generichash_blake2.c
  88. 116 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2.h
  89. 49 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c
  90. 142 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h
  91. 93 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-ref.c
  92. 87 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c
  93. 103 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h
  94. 90 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c
  95. 103 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h
  96. 340 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-load-avx2.h
  97. 164 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-load-sse2.h
  98. 307 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-load-sse41.h
  99. 438 0
      Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-ref.c
  100. 116 0
      Sources/Sodium/crypto_generichash/blake2b/ref/generichash_blake2b.c

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+.DS_Store
+/.build
+/Packages
+/*.xcodeproj
+xcuserdata/

+ 674 - 0
LICENSE

@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  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
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  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.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+  The GNU 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 Lesser General
+Public License instead of this License.  But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ 97 - 0
Package.swift

@@ -0,0 +1,97 @@
+// swift-tools-version:5.1
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+    name: "KeePass",
+
+    products: [
+        // The `Binary` manipulate bytes with ease.
+        .library(
+            name: "Binary",
+            targets: ["Binary"]),
+
+        // `Crypto` defines cryptographic interfaces used by KeePass.
+        .library(
+            name: "Crypto",
+            targets: ["Crypto"]),
+
+        // `KeePass` library defines interfaces to work with KeePass files.
+        .library(
+            name: "KeePass",
+            targets: ["KeePass"]),
+    ],
+
+    targets: [
+
+        .target(
+            name: "KeePass",
+            dependencies: [ "Binary",
+                            "KDB",
+                            "KDBX"]),
+
+        .target(
+            name: "KDB",
+            dependencies: [ "Binary",
+                            "Crypto"]),
+
+        .target(
+            name: "KDBX",
+            dependencies: [ "Binary",
+                            "Crypto",
+                            "Gzip",
+                            "XML"]),
+
+        .target(
+            name: "Binary",
+            dependencies: []),
+
+        .target(
+            name: "Crypto",
+            dependencies: [ "Binary", 
+                            "Sodium", 
+                            "Argon2", 
+                            "Twofish"]),
+
+        .target(
+            name: "Gzip",
+            dependencies: ["Binary"]),
+
+        .target(
+            name: "XML",
+            dependencies: []),
+
+        // MARK: KeePass cryptographic libraries
+
+        .target(
+            name: "Sodium",
+            dependencies: [],
+            cSettings: [
+                .headerSearchPath("include/sodium"),
+                .define("CONFIGURED")
+            ]),
+
+        .target(
+            name: "Argon2",
+            dependencies: []),
+
+        .target(
+            name: "Twofish",
+            dependencies: []),
+        
+        // MARK: Test Targets
+
+        .testTarget(
+            name: "KeePassTests",
+            dependencies: ["KeePass"]),
+
+        .testTarget(
+            name: "BinaryTests",
+            dependencies: ["Binary"]),
+
+        .testTarget(
+            name: "CryptoTests",
+            dependencies: ["Crypto"]),
+    ]
+)

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# KeePass
+
+A description of this package.

+ 314 - 0
Sources/Argon2/LICENSE

@@ -0,0 +1,314 @@
+Argon2 reference source code package - reference C implementations
+
+Copyright 2015
+Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+
+You may use this work under the terms of a Creative Commons CC0 1.0 
+License/Waiver or the Apache Public License 2.0, at your option. The terms of
+these licenses can be found at:
+
+- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+- Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+
+The terms of the licenses are reproduced below.
+
+--------------------------------------------------------------------------------
+
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+    HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+  i. the right to reproduce, adapt, distribute, perform, display,
+     communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+     likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+     subject to the limitations in paragraph 4(a), below;
+  v. rights protecting the extraction, dissemination, use and reuse of data
+     in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+     European Parliament and of the Council of 11 March 1996 on the legal
+     protection of databases, and under any national implementation
+     thereof, including any amended or successor version of such
+     directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+     world based on applicable law or treaty, and any national
+     implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+    surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+    warranties of any kind concerning the Work, express, implied,
+    statutory or otherwise, including without limitation warranties of
+    title, merchantability, fitness for a particular purpose, non
+    infringement, or the absence of latent or other defects, accuracy, or
+    the present or absence of errors, whether or not discoverable, all to
+    the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+    that may apply to the Work or any use thereof, including without
+    limitation any person's Copyright and Related Rights in the Work.
+    Further, Affirmer disclaims responsibility for obtaining any necessary
+    consents, permissions or other rights required for any use of the
+    Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+    party to this document and has no duty or obligation with respect to
+    this CC0 or use of the Work.
+
+--------------------------------------------------------------------------------
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.

+ 452 - 0
Sources/Argon2/argon2.c

@@ -0,0 +1,452 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "argon2.h"
+#include "encoding.h"
+#include "core.h"
+
+const char *argon2_type2string(argon2_type type, int uppercase) {
+    switch (type) {
+        case Argon2_d:
+            return uppercase ? "Argon2d" : "argon2d";
+        case Argon2_i:
+            return uppercase ? "Argon2i" : "argon2i";
+        case Argon2_id:
+            return uppercase ? "Argon2id" : "argon2id";
+    }
+
+    return NULL;
+}
+
+int argon2_ctx(argon2_context *context, argon2_type type) {
+    /* 1. Validate all inputs */
+    int result = validate_inputs(context);
+    uint32_t memory_blocks, segment_length;
+    argon2_instance_t instance;
+
+    if (ARGON2_OK != result) {
+        return result;
+    }
+
+    if (Argon2_d != type && Argon2_i != type && Argon2_id != type) {
+        return ARGON2_INCORRECT_TYPE;
+    }
+
+    /* 2. Align memory size */
+    /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
+    memory_blocks = context->m_cost;
+
+    if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
+        memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
+    }
+
+    segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
+    /* Ensure that all segments have equal length */
+    memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
+
+    instance.version = context->version;
+    instance.memory = NULL;
+    instance.passes = context->t_cost;
+    instance.memory_blocks = memory_blocks;
+    instance.segment_length = segment_length;
+    instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
+    instance.lanes = context->lanes;
+    instance.threads = context->threads;
+    instance.type = type;
+
+    if (instance.threads > instance.lanes) {
+        instance.threads = instance.lanes;
+    }
+
+    /* 3. Initialization: Hashing inputs, allocating memory, filling first
+     * blocks
+     */
+    result = initialize(&instance, context);
+
+    if (ARGON2_OK != result) {
+        return result;
+    }
+
+    /* 4. Filling memory */
+    result = fill_memory_blocks(&instance);
+
+    if (ARGON2_OK != result) {
+        return result;
+    }
+    /* 5. Finalization */
+    finalize(context, &instance);
+
+    return ARGON2_OK;
+}
+
+int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
+                const uint32_t parallelism, const void *pwd,
+                const size_t pwdlen, const void *salt, const size_t saltlen,
+                void *hash, const size_t hashlen, char *encoded,
+                const size_t encodedlen, argon2_type type,
+                const uint32_t version){
+
+    argon2_context context;
+    int result;
+    uint8_t *out;
+
+    if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
+        return ARGON2_PWD_TOO_LONG;
+    }
+
+    if (saltlen > ARGON2_MAX_SALT_LENGTH) {
+        return ARGON2_SALT_TOO_LONG;
+    }
+
+    if (hashlen > ARGON2_MAX_OUTLEN) {
+        return ARGON2_OUTPUT_TOO_LONG;
+    }
+
+    if (hashlen < ARGON2_MIN_OUTLEN) {
+        return ARGON2_OUTPUT_TOO_SHORT;
+    }
+
+    out = malloc(hashlen);
+    if (!out) {
+        return ARGON2_MEMORY_ALLOCATION_ERROR;
+    }
+
+    context.out = (uint8_t *)out;
+    context.outlen = (uint32_t)hashlen;
+    context.pwd = CONST_CAST(uint8_t *)pwd;
+    context.pwdlen = (uint32_t)pwdlen;
+    context.salt = CONST_CAST(uint8_t *)salt;
+    context.saltlen = (uint32_t)saltlen;
+    context.secret = NULL;
+    context.secretlen = 0;
+    context.ad = NULL;
+    context.adlen = 0;
+    context.t_cost = t_cost;
+    context.m_cost = m_cost;
+    context.lanes = parallelism;
+    context.threads = parallelism;
+    context.allocate_cbk = NULL;
+    context.free_cbk = NULL;
+    context.flags = ARGON2_DEFAULT_FLAGS;
+    context.version = version;
+
+    result = argon2_ctx(&context, type);
+
+    if (result != ARGON2_OK) {
+        clear_internal_memory(out, hashlen);
+        free(out);
+        return result;
+    }
+
+    /* if raw hash requested, write it */
+    if (hash) {
+        memcpy(hash, out, hashlen);
+    }
+
+    /* if encoding requested, write it */
+    if (encoded && encodedlen) {
+        if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
+            clear_internal_memory(out, hashlen); /* wipe buffers if error */
+            clear_internal_memory(encoded, encodedlen);
+            free(out);
+            return ARGON2_ENCODING_FAIL;
+        }
+    }
+    clear_internal_memory(out, hashlen);
+    free(out);
+
+    return ARGON2_OK;
+}
+
+int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+                         const uint32_t parallelism, const void *pwd,
+                         const size_t pwdlen, const void *salt,
+                         const size_t saltlen, const size_t hashlen,
+                         char *encoded, const size_t encodedlen) {
+
+    return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+                       NULL, hashlen, encoded, encodedlen, Argon2_i,
+                       ARGON2_VERSION_NUMBER);
+}
+
+int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+                     const uint32_t parallelism, const void *pwd,
+                     const size_t pwdlen, const void *salt,
+                     const size_t saltlen, void *hash, const size_t hashlen) {
+
+    return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+                       hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER);
+}
+
+int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+                         const uint32_t parallelism, const void *pwd,
+                         const size_t pwdlen, const void *salt,
+                         const size_t saltlen, const size_t hashlen,
+                         char *encoded, const size_t encodedlen) {
+
+    return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+                       NULL, hashlen, encoded, encodedlen, Argon2_d,
+                       ARGON2_VERSION_NUMBER);
+}
+
+int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+                     const uint32_t parallelism, const void *pwd,
+                     const size_t pwdlen, const void *salt,
+                     const size_t saltlen, void *hash, const size_t hashlen) {
+
+    return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+                       hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER);
+}
+
+int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+                          const uint32_t parallelism, const void *pwd,
+                          const size_t pwdlen, const void *salt,
+                          const size_t saltlen, const size_t hashlen,
+                          char *encoded, const size_t encodedlen) {
+
+    return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+                       NULL, hashlen, encoded, encodedlen, Argon2_id,
+                       ARGON2_VERSION_NUMBER);
+}
+
+int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+                      const uint32_t parallelism, const void *pwd,
+                      const size_t pwdlen, const void *salt,
+                      const size_t saltlen, void *hash, const size_t hashlen) {
+    return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+                       hash, hashlen, NULL, 0, Argon2_id,
+                       ARGON2_VERSION_NUMBER);
+}
+
+static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
+    size_t i;
+    uint8_t d = 0U;
+
+    for (i = 0U; i < len; i++) {
+        d |= b1[i] ^ b2[i];
+    }
+    return (int)((1 & ((d - 1) >> 8)) - 1);
+}
+
+int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
+                  argon2_type type) {
+
+    argon2_context ctx;
+    uint8_t *desired_result = NULL;
+
+    int ret = ARGON2_OK;
+
+    size_t encoded_len;
+    uint32_t max_field_len;
+
+    if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
+        return ARGON2_PWD_TOO_LONG;
+    }
+
+    if (encoded == NULL) {
+        return ARGON2_DECODING_FAIL;
+    }
+
+    encoded_len = strlen(encoded);
+    if (encoded_len > UINT32_MAX) {
+        return ARGON2_DECODING_FAIL;
+    }
+
+    /* No field can be longer than the encoded length */
+    max_field_len = (uint32_t)encoded_len;
+
+    ctx.saltlen = max_field_len;
+    ctx.outlen = max_field_len;
+
+    ctx.salt = malloc(ctx.saltlen);
+    ctx.out = malloc(ctx.outlen);
+    if (!ctx.salt || !ctx.out) {
+        ret = ARGON2_MEMORY_ALLOCATION_ERROR;
+        goto fail;
+    }
+
+    ctx.pwd = (uint8_t *)pwd;
+    ctx.pwdlen = (uint32_t)pwdlen;
+
+    ret = decode_string(&ctx, encoded, type);
+    if (ret != ARGON2_OK) {
+        goto fail;
+    }
+
+    /* Set aside the desired result, and get a new buffer. */
+    desired_result = ctx.out;
+    ctx.out = malloc(ctx.outlen);
+    if (!ctx.out) {
+        ret = ARGON2_MEMORY_ALLOCATION_ERROR;
+        goto fail;
+    }
+
+    ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
+    if (ret != ARGON2_OK) {
+        goto fail;
+    }
+
+fail:
+    free(ctx.salt);
+    free(ctx.out);
+    free(desired_result);
+
+    return ret;
+}
+
+int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
+
+    return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
+}
+
+int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
+
+    return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
+}
+
+int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
+
+    return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
+}
+
+int argon2d_ctx(argon2_context *context) {
+    return argon2_ctx(context, Argon2_d);
+}
+
+int argon2i_ctx(argon2_context *context) {
+    return argon2_ctx(context, Argon2_i);
+}
+
+int argon2id_ctx(argon2_context *context) {
+    return argon2_ctx(context, Argon2_id);
+}
+
+int argon2_verify_ctx(argon2_context *context, const char *hash,
+                      argon2_type type) {
+    int ret = argon2_ctx(context, type);
+    if (ret != ARGON2_OK) {
+        return ret;
+    }
+
+    if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) {
+        return ARGON2_VERIFY_MISMATCH;
+    }
+
+    return ARGON2_OK;
+}
+
+int argon2d_verify_ctx(argon2_context *context, const char *hash) {
+    return argon2_verify_ctx(context, hash, Argon2_d);
+}
+
+int argon2i_verify_ctx(argon2_context *context, const char *hash) {
+    return argon2_verify_ctx(context, hash, Argon2_i);
+}
+
+int argon2id_verify_ctx(argon2_context *context, const char *hash) {
+    return argon2_verify_ctx(context, hash, Argon2_id);
+}
+
+const char *argon2_error_message(int error_code) {
+    switch (error_code) {
+    case ARGON2_OK:
+        return "OK";
+    case ARGON2_OUTPUT_PTR_NULL:
+        return "Output pointer is NULL";
+    case ARGON2_OUTPUT_TOO_SHORT:
+        return "Output is too short";
+    case ARGON2_OUTPUT_TOO_LONG:
+        return "Output is too long";
+    case ARGON2_PWD_TOO_SHORT:
+        return "Password is too short";
+    case ARGON2_PWD_TOO_LONG:
+        return "Password is too long";
+    case ARGON2_SALT_TOO_SHORT:
+        return "Salt is too short";
+    case ARGON2_SALT_TOO_LONG:
+        return "Salt is too long";
+    case ARGON2_AD_TOO_SHORT:
+        return "Associated data is too short";
+    case ARGON2_AD_TOO_LONG:
+        return "Associated data is too long";
+    case ARGON2_SECRET_TOO_SHORT:
+        return "Secret is too short";
+    case ARGON2_SECRET_TOO_LONG:
+        return "Secret is too long";
+    case ARGON2_TIME_TOO_SMALL:
+        return "Time cost is too small";
+    case ARGON2_TIME_TOO_LARGE:
+        return "Time cost is too large";
+    case ARGON2_MEMORY_TOO_LITTLE:
+        return "Memory cost is too small";
+    case ARGON2_MEMORY_TOO_MUCH:
+        return "Memory cost is too large";
+    case ARGON2_LANES_TOO_FEW:
+        return "Too few lanes";
+    case ARGON2_LANES_TOO_MANY:
+        return "Too many lanes";
+    case ARGON2_PWD_PTR_MISMATCH:
+        return "Password pointer is NULL, but password length is not 0";
+    case ARGON2_SALT_PTR_MISMATCH:
+        return "Salt pointer is NULL, but salt length is not 0";
+    case ARGON2_SECRET_PTR_MISMATCH:
+        return "Secret pointer is NULL, but secret length is not 0";
+    case ARGON2_AD_PTR_MISMATCH:
+        return "Associated data pointer is NULL, but ad length is not 0";
+    case ARGON2_MEMORY_ALLOCATION_ERROR:
+        return "Memory allocation error";
+    case ARGON2_FREE_MEMORY_CBK_NULL:
+        return "The free memory callback is NULL";
+    case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
+        return "The allocate memory callback is NULL";
+    case ARGON2_INCORRECT_PARAMETER:
+        return "Argon2_Context context is NULL";
+    case ARGON2_INCORRECT_TYPE:
+        return "There is no such version of Argon2";
+    case ARGON2_OUT_PTR_MISMATCH:
+        return "Output pointer mismatch";
+    case ARGON2_THREADS_TOO_FEW:
+        return "Not enough threads";
+    case ARGON2_THREADS_TOO_MANY:
+        return "Too many threads";
+    case ARGON2_MISSING_ARGS:
+        return "Missing arguments";
+    case ARGON2_ENCODING_FAIL:
+        return "Encoding failed";
+    case ARGON2_DECODING_FAIL:
+        return "Decoding failed";
+    case ARGON2_THREAD_FAIL:
+        return "Threading failure";
+    case ARGON2_DECODING_LENGTH_FAIL:
+        return "Some of encoded parameters are too long or too short";
+    case ARGON2_VERIFY_MISMATCH:
+        return "The password does not match the supplied hash";
+    default:
+        return "Unknown error code";
+    }
+}
+
+size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
+                         uint32_t saltlen, uint32_t hashlen, argon2_type type) {
+  return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
+         numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
+         b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1;
+}

+ 390 - 0
Sources/Argon2/blake2b.c

@@ -0,0 +1,390 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "blake2/blake2.h"
+#include "blake2/blake2-impl.h"
+
+static const uint64_t blake2b_IV[8] = {
+    UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
+    UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
+    UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
+    UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
+
+static const unsigned int blake2b_sigma[12][16] = {
+    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+    {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
+    {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
+    {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
+    {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
+    {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
+    {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
+    {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
+    {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
+    {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
+    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+    {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
+};
+
+static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
+    S->f[1] = (uint64_t)-1;
+}
+
+static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
+    if (S->last_node) {
+        blake2b_set_lastnode(S);
+    }
+    S->f[0] = (uint64_t)-1;
+}
+
+static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
+                                                    uint64_t inc) {
+    S->t[0] += inc;
+    S->t[1] += (S->t[0] < inc);
+}
+
+static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
+    clear_internal_memory(S, sizeof(*S));      /* wipe */
+    blake2b_set_lastblock(S); /* invalidate for further use */
+}
+
+static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
+    memset(S, 0, sizeof(*S));
+    memcpy(S->h, blake2b_IV, sizeof(S->h));
+}
+
+int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
+    const unsigned char *p = (const unsigned char *)P;
+    unsigned int i;
+
+    if (NULL == P || NULL == S) {
+        return -1;
+    }
+
+    blake2b_init0(S);
+    /* IV XOR Parameter Block */
+    for (i = 0; i < 8; ++i) {
+        S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
+    }
+    S->outlen = P->digest_length;
+    return 0;
+}
+
+/* Sequential blake2b initialization */
+int blake2b_init(blake2b_state *S, size_t outlen) {
+    blake2b_param P;
+
+    if (S == NULL) {
+        return -1;
+    }
+
+    if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
+        blake2b_invalidate_state(S);
+        return -1;
+    }
+
+    /* Setup Parameter Block for unkeyed BLAKE2 */
+    P.digest_length = (uint8_t)outlen;
+    P.key_length = 0;
+    P.fanout = 1;
+    P.depth = 1;
+    P.leaf_length = 0;
+    P.node_offset = 0;
+    P.node_depth = 0;
+    P.inner_length = 0;
+    memset(P.reserved, 0, sizeof(P.reserved));
+    memset(P.salt, 0, sizeof(P.salt));
+    memset(P.personal, 0, sizeof(P.personal));
+
+    return blake2b_init_param(S, &P);
+}
+
+int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
+                     size_t keylen) {
+    blake2b_param P;
+
+    if (S == NULL) {
+        return -1;
+    }
+
+    if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
+        blake2b_invalidate_state(S);
+        return -1;
+    }
+
+    if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) {
+        blake2b_invalidate_state(S);
+        return -1;
+    }
+
+    /* Setup Parameter Block for keyed BLAKE2 */
+    P.digest_length = (uint8_t)outlen;
+    P.key_length = (uint8_t)keylen;
+    P.fanout = 1;
+    P.depth = 1;
+    P.leaf_length = 0;
+    P.node_offset = 0;
+    P.node_depth = 0;
+    P.inner_length = 0;
+    memset(P.reserved, 0, sizeof(P.reserved));
+    memset(P.salt, 0, sizeof(P.salt));
+    memset(P.personal, 0, sizeof(P.personal));
+
+    if (blake2b_init_param(S, &P) < 0) {
+        blake2b_invalidate_state(S);
+        return -1;
+    }
+
+    {
+        uint8_t block[BLAKE2B_BLOCKBYTES];
+        memset(block, 0, BLAKE2B_BLOCKBYTES);
+        memcpy(block, key, keylen);
+        blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
+        /* Burn the key from stack */
+        clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
+    }
+    return 0;
+}
+
+static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
+    uint64_t m[16];
+    uint64_t v[16];
+    unsigned int i, r;
+
+    for (i = 0; i < 16; ++i) {
+        m[i] = load64(block + i * sizeof(m[i]));
+    }
+
+    for (i = 0; i < 8; ++i) {
+        v[i] = S->h[i];
+    }
+
+    v[8] = blake2b_IV[0];
+    v[9] = blake2b_IV[1];
+    v[10] = blake2b_IV[2];
+    v[11] = blake2b_IV[3];
+    v[12] = blake2b_IV[4] ^ S->t[0];
+    v[13] = blake2b_IV[5] ^ S->t[1];
+    v[14] = blake2b_IV[6] ^ S->f[0];
+    v[15] = blake2b_IV[7] ^ S->f[1];
+
+#define G(r, i, a, b, c, d)                                                    \
+    do {                                                                       \
+        a = a + b + m[blake2b_sigma[r][2 * i + 0]];                            \
+        d = rotr64(d ^ a, 32);                                                 \
+        c = c + d;                                                             \
+        b = rotr64(b ^ c, 24);                                                 \
+        a = a + b + m[blake2b_sigma[r][2 * i + 1]];                            \
+        d = rotr64(d ^ a, 16);                                                 \
+        c = c + d;                                                             \
+        b = rotr64(b ^ c, 63);                                                 \
+    } while ((void)0, 0)
+
+#define ROUND(r)                                                               \
+    do {                                                                       \
+        G(r, 0, v[0], v[4], v[8], v[12]);                                      \
+        G(r, 1, v[1], v[5], v[9], v[13]);                                      \
+        G(r, 2, v[2], v[6], v[10], v[14]);                                     \
+        G(r, 3, v[3], v[7], v[11], v[15]);                                     \
+        G(r, 4, v[0], v[5], v[10], v[15]);                                     \
+        G(r, 5, v[1], v[6], v[11], v[12]);                                     \
+        G(r, 6, v[2], v[7], v[8], v[13]);                                      \
+        G(r, 7, v[3], v[4], v[9], v[14]);                                      \
+    } while ((void)0, 0)
+
+    for (r = 0; r < 12; ++r) {
+        ROUND(r);
+    }
+
+    for (i = 0; i < 8; ++i) {
+        S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+    }
+
+#undef G
+#undef ROUND
+}
+
+int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
+    const uint8_t *pin = (const uint8_t *)in;
+
+    if (inlen == 0) {
+        return 0;
+    }
+
+    /* Sanity check */
+    if (S == NULL || in == NULL) {
+        return -1;
+    }
+
+    /* Is this a reused state? */
+    if (S->f[0] != 0) {
+        return -1;
+    }
+
+    if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) {
+        /* Complete current block */
+        size_t left = S->buflen;
+        size_t fill = BLAKE2B_BLOCKBYTES - left;
+        memcpy(&S->buf[left], pin, fill);
+        blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+        blake2b_compress(S, S->buf);
+        S->buflen = 0;
+        inlen -= fill;
+        pin += fill;
+        /* Avoid buffer copies when possible */
+        while (inlen > BLAKE2B_BLOCKBYTES) {
+            blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+            blake2b_compress(S, pin);
+            inlen -= BLAKE2B_BLOCKBYTES;
+            pin += BLAKE2B_BLOCKBYTES;
+        }
+    }
+    memcpy(&S->buf[S->buflen], pin, inlen);
+    S->buflen += (unsigned int)inlen;
+    return 0;
+}
+
+int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
+    uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
+    unsigned int i;
+
+    /* Sanity checks */
+    if (S == NULL || out == NULL || outlen < S->outlen) {
+        return -1;
+    }
+
+    /* Is this a reused state? */
+    if (S->f[0] != 0) {
+        return -1;
+    }
+
+    blake2b_increment_counter(S, S->buflen);
+    blake2b_set_lastblock(S);
+    memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
+    blake2b_compress(S, S->buf);
+
+    for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
+        store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
+    }
+
+    memcpy(out, buffer, S->outlen);
+    clear_internal_memory(buffer, sizeof(buffer));
+    clear_internal_memory(S->buf, sizeof(S->buf));
+    clear_internal_memory(S->h, sizeof(S->h));
+    return 0;
+}
+
+int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
+            const void *key, size_t keylen) {
+    blake2b_state S;
+    int ret = -1;
+
+    /* Verify parameters */
+    if (NULL == in && inlen > 0) {
+        goto fail;
+    }
+
+    if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) {
+        goto fail;
+    }
+
+    if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
+        goto fail;
+    }
+
+    if (keylen > 0) {
+        if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
+            goto fail;
+        }
+    } else {
+        if (blake2b_init(&S, outlen) < 0) {
+            goto fail;
+        }
+    }
+
+    if (blake2b_update(&S, in, inlen) < 0) {
+        goto fail;
+    }
+    ret = blake2b_final(&S, out, outlen);
+
+fail:
+    clear_internal_memory(&S, sizeof(S));
+    return ret;
+}
+
+/* Argon2 Team - Begin Code */
+int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
+    uint8_t *out = (uint8_t *)pout;
+    blake2b_state blake_state;
+    uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
+    int ret = -1;
+
+    if (outlen > UINT32_MAX) {
+        goto fail;
+    }
+
+    /* Ensure little-endian byte order! */
+    store32(outlen_bytes, (uint32_t)outlen);
+
+#define TRY(statement)                                                         \
+    do {                                                                       \
+        ret = statement;                                                       \
+        if (ret < 0) {                                                         \
+            goto fail;                                                         \
+        }                                                                      \
+    } while ((void)0, 0)
+
+    if (outlen <= BLAKE2B_OUTBYTES) {
+        TRY(blake2b_init(&blake_state, outlen));
+        TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
+        TRY(blake2b_update(&blake_state, in, inlen));
+        TRY(blake2b_final(&blake_state, out, outlen));
+    } else {
+        uint32_t toproduce;
+        uint8_t out_buffer[BLAKE2B_OUTBYTES];
+        uint8_t in_buffer[BLAKE2B_OUTBYTES];
+        TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
+        TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
+        TRY(blake2b_update(&blake_state, in, inlen));
+        TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
+        memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
+        out += BLAKE2B_OUTBYTES / 2;
+        toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
+
+        while (toproduce > BLAKE2B_OUTBYTES) {
+            memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
+            TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
+                        BLAKE2B_OUTBYTES, NULL, 0));
+            memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
+            out += BLAKE2B_OUTBYTES / 2;
+            toproduce -= BLAKE2B_OUTBYTES / 2;
+        }
+
+        memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
+        TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
+                    0));
+        memcpy(out, out_buffer, toproduce);
+    }
+fail:
+    clear_internal_memory(&blake_state, sizeof(blake_state));
+    return ret;
+#undef TRY
+}
+/* Argon2 Team - End Code */

+ 648 - 0
Sources/Argon2/core.c

@@ -0,0 +1,648 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+/*For memory wiping*/
+#ifdef _MSC_VER
+#include <windows.h>
+#include <winbase.h> /* For SecureZeroMemory */
+#endif
+#if defined __STDC_LIB_EXT1__
+#define __STDC_WANT_LIB_EXT1__ 1
+#endif
+#define VC_GE_2005(version) (version >= 1400)
+
+/* for explicit_bzero() on glibc */
+#define _DEFAULT_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "thread.h"
+#include "blake2/blake2.h"
+#include "blake2/blake2-impl.h"
+
+#ifdef GENKAT
+#include "genkat.h"
+#endif
+
+#if defined(__clang__)
+#if __has_attribute(optnone)
+#define NOT_OPTIMIZED __attribute__((optnone))
+#endif
+#elif defined(__GNUC__)
+#define GCC_VERSION                                                            \
+    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#if GCC_VERSION >= 40400
+#define NOT_OPTIMIZED __attribute__((optimize("O0")))
+#endif
+#endif
+#ifndef NOT_OPTIMIZED
+#define NOT_OPTIMIZED
+#endif
+
+/***************Instance and Position constructors**********/
+void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
+
+void copy_block(block *dst, const block *src) {
+    memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
+}
+
+void xor_block(block *dst, const block *src) {
+    int i;
+    for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+        dst->v[i] ^= src->v[i];
+    }
+}
+
+static void load_block(block *dst, const void *input) {
+    unsigned i;
+    for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+        dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
+    }
+}
+
+static void store_block(void *output, const block *src) {
+    unsigned i;
+    for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+        store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
+    }
+}
+
+/***************Memory functions*****************/
+
+int allocate_memory(const argon2_context *context, uint8_t **memory,
+                    size_t num, size_t size) {
+    size_t memory_size = num*size;
+    if (memory == NULL) {
+        return ARGON2_MEMORY_ALLOCATION_ERROR;
+    }
+
+    /* 1. Check for multiplication overflow */
+    if (size != 0 && memory_size / size != num) {
+        return ARGON2_MEMORY_ALLOCATION_ERROR;
+    }
+
+    /* 2. Try to allocate with appropriate allocator */
+    if (context->allocate_cbk) {
+        (context->allocate_cbk)(memory, memory_size);
+    } else {
+        *memory = malloc(memory_size);
+    }
+
+    if (*memory == NULL) {
+        return ARGON2_MEMORY_ALLOCATION_ERROR;
+    }
+
+    return ARGON2_OK;
+}
+
+void free_memory(const argon2_context *context, uint8_t *memory,
+                 size_t num, size_t size) {
+    size_t memory_size = num*size;
+    clear_internal_memory(memory, memory_size);
+    if (context->free_cbk) {
+        (context->free_cbk)(memory, memory_size);
+    } else {
+        free(memory);
+    }
+}
+
+#if defined(__OpenBSD__)
+#define HAVE_EXPLICIT_BZERO 1
+#elif defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+#if __GLIBC_PREREQ(2,25)
+#define HAVE_EXPLICIT_BZERO 1
+#endif
+#endif
+
+void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
+#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
+    SecureZeroMemory(v, n);
+#elif defined memset_s
+    memset_s(v, n, 0, n);
+#elif defined(HAVE_EXPLICIT_BZERO)
+    explicit_bzero(v, n);
+#else
+    static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
+    memset_sec(v, 0, n);
+#endif
+}
+
+/* Memory clear flag defaults to true. */
+int FLAG_clear_internal_memory = 1;
+void clear_internal_memory(void *v, size_t n) {
+  if (FLAG_clear_internal_memory && v) {
+    secure_wipe_memory(v, n);
+  }
+}
+
+void finalize(const argon2_context *context, argon2_instance_t *instance) {
+    if (context != NULL && instance != NULL) {
+        block blockhash;
+        uint32_t l;
+
+        copy_block(&blockhash, instance->memory + instance->lane_length - 1);
+
+        /* XOR the last blocks */
+        for (l = 1; l < instance->lanes; ++l) {
+            uint32_t last_block_in_lane =
+                l * instance->lane_length + (instance->lane_length - 1);
+            xor_block(&blockhash, instance->memory + last_block_in_lane);
+        }
+
+        /* Hash the result */
+        {
+            uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+            store_block(blockhash_bytes, &blockhash);
+            blake2b_long(context->out, context->outlen, blockhash_bytes,
+                         ARGON2_BLOCK_SIZE);
+            /* clear blockhash and blockhash_bytes */
+            clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE);
+            clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
+        }
+
+#ifdef GENKAT
+        print_tag(context->out, context->outlen);
+#endif
+
+        free_memory(context, (uint8_t *)instance->memory,
+                    instance->memory_blocks, sizeof(block));
+    }
+}
+
+uint32_t index_alpha(const argon2_instance_t *instance,
+                     const argon2_position_t *position, uint32_t pseudo_rand,
+                     int same_lane) {
+    /*
+     * Pass 0:
+     *      This lane : all already finished segments plus already constructed
+     * blocks in this segment
+     *      Other lanes : all already finished segments
+     * Pass 1+:
+     *      This lane : (SYNC_POINTS - 1) last segments plus already constructed
+     * blocks in this segment
+     *      Other lanes : (SYNC_POINTS - 1) last segments
+     */
+    uint32_t reference_area_size;
+    uint64_t relative_position;
+    uint32_t start_position, absolute_position;
+
+    if (0 == position->pass) {
+        /* First pass */
+        if (0 == position->slice) {
+            /* First slice */
+            reference_area_size =
+                position->index - 1; /* all but the previous */
+        } else {
+            if (same_lane) {
+                /* The same lane => add current segment */
+                reference_area_size =
+                    position->slice * instance->segment_length +
+                    position->index - 1;
+            } else {
+                reference_area_size =
+                    position->slice * instance->segment_length +
+                    ((position->index == 0) ? (-1) : 0);
+            }
+        }
+    } else {
+        /* Second pass */
+        if (same_lane) {
+            reference_area_size = instance->lane_length -
+                                  instance->segment_length + position->index -
+                                  1;
+        } else {
+            reference_area_size = instance->lane_length -
+                                  instance->segment_length +
+                                  ((position->index == 0) ? (-1) : 0);
+        }
+    }
+
+    /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
+     * relative position */
+    relative_position = pseudo_rand;
+    relative_position = relative_position * relative_position >> 32;
+    relative_position = reference_area_size - 1 -
+                        (reference_area_size * relative_position >> 32);
+
+    /* 1.2.5 Computing starting position */
+    start_position = 0;
+
+    if (0 != position->pass) {
+        start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
+                             ? 0
+                             : (position->slice + 1) * instance->segment_length;
+    }
+
+    /* 1.2.6. Computing absolute position */
+    absolute_position = (start_position + relative_position) %
+                        instance->lane_length; /* absolute position */
+    return absolute_position;
+}
+
+/* Single-threaded version for p=1 case */
+static int fill_memory_blocks_st(argon2_instance_t *instance) {
+    uint32_t r, s, l;
+
+    for (r = 0; r < instance->passes; ++r) {
+        for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
+            for (l = 0; l < instance->lanes; ++l) {
+                argon2_position_t position = {r, l, (uint8_t)s, 0};
+                fill_segment(instance, position);
+            }
+        }
+#ifdef GENKAT
+        internal_kat(instance, r); /* Print all memory blocks */
+#endif
+    }
+    return ARGON2_OK;
+}
+
+#if !defined(ARGON2_NO_THREADS)
+
+#ifdef _WIN32
+static unsigned __stdcall fill_segment_thr(void *thread_data)
+#else
+static void *fill_segment_thr(void *thread_data)
+#endif
+{
+    argon2_thread_data *my_data = thread_data;
+    fill_segment(my_data->instance_ptr, my_data->pos);
+    argon2_thread_exit();
+    return 0;
+}
+
+/* Multi-threaded version for p > 1 case */
+static int fill_memory_blocks_mt(argon2_instance_t *instance) {
+    uint32_t r, s;
+    argon2_thread_handle_t *thread = NULL;
+    argon2_thread_data *thr_data = NULL;
+    int rc = ARGON2_OK;
+
+    /* 1. Allocating space for threads */
+    thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t));
+    if (thread == NULL) {
+        rc = ARGON2_MEMORY_ALLOCATION_ERROR;
+        goto fail;
+    }
+
+    thr_data = calloc(instance->lanes, sizeof(argon2_thread_data));
+    if (thr_data == NULL) {
+        rc = ARGON2_MEMORY_ALLOCATION_ERROR;
+        goto fail;
+    }
+
+    for (r = 0; r < instance->passes; ++r) {
+        for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
+            uint32_t l, ll;
+
+            /* 2. Calling threads */
+            for (l = 0; l < instance->lanes; ++l) {
+                argon2_position_t position;
+
+                /* 2.1 Join a thread if limit is exceeded */
+                if (l >= instance->threads) {
+                    if (argon2_thread_join(thread[l - instance->threads])) {
+                        rc = ARGON2_THREAD_FAIL;
+                        goto fail;
+                    }
+                }
+
+                /* 2.2 Create thread */
+                position.pass = r;
+                position.lane = l;
+                position.slice = (uint8_t)s;
+                position.index = 0;
+                thr_data[l].instance_ptr =
+                    instance; /* preparing the thread input */
+                memcpy(&(thr_data[l].pos), &position,
+                       sizeof(argon2_position_t));
+                if (argon2_thread_create(&thread[l], &fill_segment_thr,
+                                         (void *)&thr_data[l])) {
+                    /* Wait for already running threads */
+                    for (ll = 0; ll < l; ++ll)
+                        argon2_thread_join(thread[ll]);
+                    rc = ARGON2_THREAD_FAIL;
+                    goto fail;
+                }
+
+                /* fill_segment(instance, position); */
+                /*Non-thread equivalent of the lines above */
+            }
+
+            /* 3. Joining remaining threads */
+            for (l = instance->lanes - instance->threads; l < instance->lanes;
+                 ++l) {
+                if (argon2_thread_join(thread[l])) {
+                    rc = ARGON2_THREAD_FAIL;
+                    goto fail;
+                }
+            }
+        }
+
+#ifdef GENKAT
+        internal_kat(instance, r); /* Print all memory blocks */
+#endif
+    }
+
+fail:
+    if (thread != NULL) {
+        free(thread);
+    }
+    if (thr_data != NULL) {
+        free(thr_data);
+    }
+    return rc;
+}
+
+#endif /* ARGON2_NO_THREADS */
+
+int fill_memory_blocks(argon2_instance_t *instance) {
+	if (instance == NULL || instance->lanes == 0) {
+	    return ARGON2_INCORRECT_PARAMETER;
+    }
+#if defined(ARGON2_NO_THREADS)
+    return fill_memory_blocks_st(instance);
+#else
+    return instance->threads == 1 ?
+			fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
+#endif
+}
+
+int validate_inputs(const argon2_context *context) {
+    if (NULL == context) {
+        return ARGON2_INCORRECT_PARAMETER;
+    }
+
+    if (NULL == context->out) {
+        return ARGON2_OUTPUT_PTR_NULL;
+    }
+
+    /* Validate output length */
+    if (ARGON2_MIN_OUTLEN > context->outlen) {
+        return ARGON2_OUTPUT_TOO_SHORT;
+    }
+
+    if (ARGON2_MAX_OUTLEN < context->outlen) {
+        return ARGON2_OUTPUT_TOO_LONG;
+    }
+
+    /* Validate password (required param) */
+    if (NULL == context->pwd) {
+        if (0 != context->pwdlen) {
+            return ARGON2_PWD_PTR_MISMATCH;
+        }
+    }
+
+    if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
+      return ARGON2_PWD_TOO_SHORT;
+    }
+
+    if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
+        return ARGON2_PWD_TOO_LONG;
+    }
+
+    /* Validate salt (required param) */
+    if (NULL == context->salt) {
+        if (0 != context->saltlen) {
+            return ARGON2_SALT_PTR_MISMATCH;
+        }
+    }
+
+    if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
+        return ARGON2_SALT_TOO_SHORT;
+    }
+
+    if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
+        return ARGON2_SALT_TOO_LONG;
+    }
+
+    /* Validate secret (optional param) */
+    if (NULL == context->secret) {
+        if (0 != context->secretlen) {
+            return ARGON2_SECRET_PTR_MISMATCH;
+        }
+    } else {
+        if (ARGON2_MIN_SECRET > context->secretlen) {
+            return ARGON2_SECRET_TOO_SHORT;
+        }
+        if (ARGON2_MAX_SECRET < context->secretlen) {
+            return ARGON2_SECRET_TOO_LONG;
+        }
+    }
+
+    /* Validate associated data (optional param) */
+    if (NULL == context->ad) {
+        if (0 != context->adlen) {
+            return ARGON2_AD_PTR_MISMATCH;
+        }
+    } else {
+        if (ARGON2_MIN_AD_LENGTH > context->adlen) {
+            return ARGON2_AD_TOO_SHORT;
+        }
+        if (ARGON2_MAX_AD_LENGTH < context->adlen) {
+            return ARGON2_AD_TOO_LONG;
+        }
+    }
+
+    /* Validate memory cost */
+    if (ARGON2_MIN_MEMORY > context->m_cost) {
+        return ARGON2_MEMORY_TOO_LITTLE;
+    }
+
+    if (ARGON2_MAX_MEMORY < context->m_cost) {
+        return ARGON2_MEMORY_TOO_MUCH;
+    }
+
+    if (context->m_cost < 8 * context->lanes) {
+        return ARGON2_MEMORY_TOO_LITTLE;
+    }
+
+    /* Validate time cost */
+    if (ARGON2_MIN_TIME > context->t_cost) {
+        return ARGON2_TIME_TOO_SMALL;
+    }
+
+    if (ARGON2_MAX_TIME < context->t_cost) {
+        return ARGON2_TIME_TOO_LARGE;
+    }
+
+    /* Validate lanes */
+    if (ARGON2_MIN_LANES > context->lanes) {
+        return ARGON2_LANES_TOO_FEW;
+    }
+
+    if (ARGON2_MAX_LANES < context->lanes) {
+        return ARGON2_LANES_TOO_MANY;
+    }
+
+    /* Validate threads */
+    if (ARGON2_MIN_THREADS > context->threads) {
+        return ARGON2_THREADS_TOO_FEW;
+    }
+
+    if (ARGON2_MAX_THREADS < context->threads) {
+        return ARGON2_THREADS_TOO_MANY;
+    }
+
+    if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
+        return ARGON2_FREE_MEMORY_CBK_NULL;
+    }
+
+    if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
+        return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
+    }
+
+    return ARGON2_OK;
+}
+
+void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
+    uint32_t l;
+    /* Make the first and second block in each lane as G(H0||0||i) or
+       G(H0||1||i) */
+    uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+    for (l = 0; l < instance->lanes; ++l) {
+
+        store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
+        store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
+        blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+                     ARGON2_PREHASH_SEED_LENGTH);
+        load_block(&instance->memory[l * instance->lane_length + 0],
+                   blockhash_bytes);
+
+        store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
+        blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+                     ARGON2_PREHASH_SEED_LENGTH);
+        load_block(&instance->memory[l * instance->lane_length + 1],
+                   blockhash_bytes);
+    }
+    clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
+}
+
+void initial_hash(uint8_t *blockhash, argon2_context *context,
+                  argon2_type type) {
+    blake2b_state BlakeHash;
+    uint8_t value[sizeof(uint32_t)];
+
+    if (NULL == context || NULL == blockhash) {
+        return;
+    }
+
+    blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
+
+    store32(&value, context->lanes);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    store32(&value, context->outlen);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    store32(&value, context->m_cost);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    store32(&value, context->t_cost);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    store32(&value, context->version);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    store32(&value, (uint32_t)type);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    store32(&value, context->pwdlen);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    if (context->pwd != NULL) {
+        blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
+                       context->pwdlen);
+
+        if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
+            secure_wipe_memory(context->pwd, context->pwdlen);
+            context->pwdlen = 0;
+        }
+    }
+
+    store32(&value, context->saltlen);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    if (context->salt != NULL) {
+        blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
+                       context->saltlen);
+    }
+
+    store32(&value, context->secretlen);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    if (context->secret != NULL) {
+        blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
+                       context->secretlen);
+
+        if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
+            secure_wipe_memory(context->secret, context->secretlen);
+            context->secretlen = 0;
+        }
+    }
+
+    store32(&value, context->adlen);
+    blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+    if (context->ad != NULL) {
+        blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
+                       context->adlen);
+    }
+
+    blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
+}
+
+int initialize(argon2_instance_t *instance, argon2_context *context) {
+    uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
+    int result = ARGON2_OK;
+
+    if (instance == NULL || context == NULL)
+        return ARGON2_INCORRECT_PARAMETER;
+    instance->context_ptr = context;
+
+    /* 1. Memory allocation */
+    result = allocate_memory(context, (uint8_t **)&(instance->memory),
+                             instance->memory_blocks, sizeof(block));
+    if (result != ARGON2_OK) {
+        return result;
+    }
+
+    /* 2. Initial hashing */
+    /* H_0 + 8 extra bytes to produce the first blocks */
+    /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
+    /* Hashing all inputs */
+    initial_hash(blockhash, context, instance->type);
+    /* Zeroing 8 extra bytes */
+    clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
+                          ARGON2_PREHASH_SEED_LENGTH -
+                              ARGON2_PREHASH_DIGEST_LENGTH);
+
+#ifdef GENKAT
+    initial_kat(blockhash, context, instance->type);
+#endif
+
+    /* 3. Creating first blocks, we always have at least two blocks in a slice
+     */
+    fill_first_blocks(blockhash, instance);
+    /* Clearing the hash */
+    clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
+
+    return ARGON2_OK;
+}

+ 463 - 0
Sources/Argon2/encoding.c

@@ -0,0 +1,463 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "encoding.h"
+#include "core.h"
+
+/*
+ * Example code for a decoder and encoder of "hash strings", with Argon2
+ * parameters.
+ *
+ * This code comprises three sections:
+ *
+ *   -- The first section contains generic Base64 encoding and decoding
+ *   functions. It is conceptually applicable to any hash function
+ *   implementation that uses Base64 to encode and decode parameters,
+ *   salts and outputs. It could be made into a library, provided that
+ *   the relevant functions are made public (non-static) and be given
+ *   reasonable names to avoid collisions with other functions.
+ *
+ *   -- The second section is specific to Argon2. It encodes and decodes
+ *   the parameters, salts and outputs. It does not compute the hash
+ *   itself.
+ *
+ * The code was originally written by Thomas Pornin <pornin@bolet.org>,
+ * to whom comments and remarks may be sent. It is released under what
+ * should amount to Public Domain or its closest equivalent; the
+ * following mantra is supposed to incarnate that fact with all the
+ * proper legal rituals:
+ *
+ * ---------------------------------------------------------------------
+ * This file is provided under the terms of Creative Commons CC0 1.0
+ * Public Domain Dedication. To the extent possible under law, the
+ * author (Thomas Pornin) has waived all copyright and related or
+ * neighboring rights to this file. This work is published from: Canada.
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2015 Thomas Pornin
+ */
+
+/* ==================================================================== */
+/*
+ * Common code; could be shared between different hash functions.
+ *
+ * Note: the Base64 functions below assume that uppercase letters (resp.
+ * lowercase letters) have consecutive numerical codes, that fit on 8
+ * bits. All modern systems use ASCII-compatible charsets, where these
+ * properties are true. If you are stuck with a dinosaur of a system
+ * that still defaults to EBCDIC then you already have much bigger
+ * interoperability issues to deal with.
+ */
+
+/*
+ * Some macros for constant-time comparisons. These work over values in
+ * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
+ */
+#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
+#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
+#define GE(x, y) (GT(y, x) ^ 0xFF)
+#define LT(x, y) GT(y, x)
+#define LE(x, y) GE(y, x)
+
+/*
+ * Convert value x (0..63) to corresponding Base64 character.
+ */
+static int b64_byte_to_char(unsigned x) {
+    return (LT(x, 26) & (x + 'A')) |
+           (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
+           (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
+           (EQ(x, 63) & '/');
+}
+
+/*
+ * Convert character c to the corresponding 6-bit value. If character c
+ * is not a Base64 character, then 0xFF (255) is returned.
+ */
+static unsigned b64_char_to_byte(int c) {
+    unsigned x;
+
+    x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
+        (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
+        (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
+        (EQ(c, '/') & 63);
+    return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
+}
+
+/*
+ * Convert some bytes to Base64. 'dst_len' is the length (in characters)
+ * of the output buffer 'dst'; if that buffer is not large enough to
+ * receive the result (including the terminating 0), then (size_t)-1
+ * is returned. Otherwise, the zero-terminated Base64 string is written
+ * in the buffer, and the output length (counted WITHOUT the terminating
+ * zero) is returned.
+ */
+static size_t to_base64(char *dst, size_t dst_len, const void *src,
+                        size_t src_len) {
+    size_t olen;
+    const unsigned char *buf;
+    unsigned acc, acc_len;
+
+    olen = (src_len / 3) << 2;
+    switch (src_len % 3) {
+    case 2:
+        olen++;
+    /* fall through */
+    case 1:
+        olen += 2;
+        break;
+    }
+    if (dst_len <= olen) {
+        return (size_t)-1;
+    }
+    acc = 0;
+    acc_len = 0;
+    buf = (const unsigned char *)src;
+    while (src_len-- > 0) {
+        acc = (acc << 8) + (*buf++);
+        acc_len += 8;
+        while (acc_len >= 6) {
+            acc_len -= 6;
+            *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
+        }
+    }
+    if (acc_len > 0) {
+        *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
+    }
+    *dst++ = 0;
+    return olen;
+}
+
+/*
+ * Decode Base64 chars into bytes. The '*dst_len' value must initially
+ * contain the length of the output buffer '*dst'; when the decoding
+ * ends, the actual number of decoded bytes is written back in
+ * '*dst_len'.
+ *
+ * Decoding stops when a non-Base64 character is encountered, or when
+ * the output buffer capacity is exceeded. If an error occurred (output
+ * buffer is too small, invalid last characters leading to unprocessed
+ * buffered bits), then NULL is returned; otherwise, the returned value
+ * points to the first non-Base64 character in the source stream, which
+ * may be the terminating zero.
+ */
+static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
+    size_t len;
+    unsigned char *buf;
+    unsigned acc, acc_len;
+
+    buf = (unsigned char *)dst;
+    len = 0;
+    acc = 0;
+    acc_len = 0;
+    for (;;) {
+        unsigned d;
+
+        d = b64_char_to_byte(*src);
+        if (d == 0xFF) {
+            break;
+        }
+        src++;
+        acc = (acc << 6) + d;
+        acc_len += 6;
+        if (acc_len >= 8) {
+            acc_len -= 8;
+            if ((len++) >= *dst_len) {
+                return NULL;
+            }
+            *buf++ = (acc >> acc_len) & 0xFF;
+        }
+    }
+
+    /*
+     * If the input length is equal to 1 modulo 4 (which is
+     * invalid), then there will remain 6 unprocessed bits;
+     * otherwise, only 0, 2 or 4 bits are buffered. The buffered
+     * bits must also all be zero.
+     */
+    if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
+        return NULL;
+    }
+    *dst_len = len;
+    return src;
+}
+
+/*
+ * Decode decimal integer from 'str'; the value is written in '*v'.
+ * Returned value is a pointer to the next non-decimal character in the
+ * string. If there is no digit at all, or the value encoding is not
+ * minimal (extra leading zeros), or the value does not fit in an
+ * 'unsigned long', then NULL is returned.
+ */
+static const char *decode_decimal(const char *str, unsigned long *v) {
+    const char *orig;
+    unsigned long acc;
+
+    acc = 0;
+    for (orig = str;; str++) {
+        int c;
+
+        c = *str;
+        if (c < '0' || c > '9') {
+            break;
+        }
+        c -= '0';
+        if (acc > (ULONG_MAX / 10)) {
+            return NULL;
+        }
+        acc *= 10;
+        if ((unsigned long)c > (ULONG_MAX - acc)) {
+            return NULL;
+        }
+        acc += (unsigned long)c;
+    }
+    if (str == orig || (*orig == '0' && str != (orig + 1))) {
+        return NULL;
+    }
+    *v = acc;
+    return str;
+}
+
+/* ==================================================================== */
+/*
+ * Code specific to Argon2.
+ *
+ * The code below applies the following format:
+ *
+ *  $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
+ *
+ * where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
+ * fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
+ * characters, no newline or whitespace).
+ *
+ * The last two binary chunks (encoded in Base64) are, in that order,
+ * the salt and the output. Both are required. The binary salt length and the
+ * output length must be in the allowed ranges defined in argon2.h.
+ *
+ * The ctx struct must contain buffers large enough to hold the salt and pwd
+ * when it is fed into decode_string.
+ */
+
+int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
+
+/* check for prefix */
+#define CC(prefix)                                                             \
+    do {                                                                       \
+        size_t cc_len = strlen(prefix);                                        \
+        if (strncmp(str, prefix, cc_len) != 0) {                               \
+            return ARGON2_DECODING_FAIL;                                       \
+        }                                                                      \
+        str += cc_len;                                                         \
+    } while ((void)0, 0)
+
+/* optional prefix checking with supplied code */
+#define CC_opt(prefix, code)                                                   \
+    do {                                                                       \
+        size_t cc_len = strlen(prefix);                                        \
+        if (strncmp(str, prefix, cc_len) == 0) {                               \
+            str += cc_len;                                                     \
+            { code; }                                                          \
+        }                                                                      \
+    } while ((void)0, 0)
+
+/* Decoding prefix into decimal */
+#define DECIMAL(x)                                                             \
+    do {                                                                       \
+        unsigned long dec_x;                                                   \
+        str = decode_decimal(str, &dec_x);                                     \
+        if (str == NULL) {                                                     \
+            return ARGON2_DECODING_FAIL;                                       \
+        }                                                                      \
+        (x) = dec_x;                                                           \
+    } while ((void)0, 0)
+
+
+/* Decoding prefix into uint32_t decimal */
+#define DECIMAL_U32(x)                                                         \
+    do {                                                                       \
+        unsigned long dec_x;                                                   \
+        str = decode_decimal(str, &dec_x);                                     \
+        if (str == NULL || dec_x > UINT32_MAX) {                               \
+            return ARGON2_DECODING_FAIL;                                       \
+        }                                                                      \
+        (x) = (uint32_t)dec_x;                                                 \
+    } while ((void)0, 0)
+
+
+/* Decoding base64 into a binary buffer */
+#define BIN(buf, max_len, len)                                                 \
+    do {                                                                       \
+        size_t bin_len = (max_len);                                            \
+        str = from_base64(buf, &bin_len, str);                                 \
+        if (str == NULL || bin_len > UINT32_MAX) {                             \
+            return ARGON2_DECODING_FAIL;                                       \
+        }                                                                      \
+        (len) = (uint32_t)bin_len;                                             \
+    } while ((void)0, 0)
+
+    size_t maxsaltlen = ctx->saltlen;
+    size_t maxoutlen = ctx->outlen;
+    int validation_result;
+    const char* type_string;
+
+    /* We should start with the argon2_type we are using */
+    type_string = argon2_type2string(type, 0);
+    if (!type_string) {
+        return ARGON2_INCORRECT_TYPE;
+    }
+
+    CC("$");
+    CC(type_string);
+
+    /* Reading the version number if the default is suppressed */
+    ctx->version = ARGON2_VERSION_10;
+    CC_opt("$v=", DECIMAL_U32(ctx->version));
+
+    CC("$m=");
+    DECIMAL_U32(ctx->m_cost);
+    CC(",t=");
+    DECIMAL_U32(ctx->t_cost);
+    CC(",p=");
+    DECIMAL_U32(ctx->lanes);
+    ctx->threads = ctx->lanes;
+
+    CC("$");
+    BIN(ctx->salt, maxsaltlen, ctx->saltlen);
+    CC("$");
+    BIN(ctx->out, maxoutlen, ctx->outlen);
+
+    /* The rest of the fields get the default values */
+    ctx->secret = NULL;
+    ctx->secretlen = 0;
+    ctx->ad = NULL;
+    ctx->adlen = 0;
+    ctx->allocate_cbk = NULL;
+    ctx->free_cbk = NULL;
+    ctx->flags = ARGON2_DEFAULT_FLAGS;
+
+    /* On return, must have valid context */
+    validation_result = validate_inputs(ctx);
+    if (validation_result != ARGON2_OK) {
+        return validation_result;
+    }
+
+    /* Can't have any additional characters */
+    if (*str == 0) {
+        return ARGON2_OK;
+    } else {
+        return ARGON2_DECODING_FAIL;
+    }
+#undef CC
+#undef CC_opt
+#undef DECIMAL
+#undef BIN
+}
+
+int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
+                  argon2_type type) {
+#define SS(str)                                                                \
+    do {                                                                       \
+        size_t pp_len = strlen(str);                                           \
+        if (pp_len >= dst_len) {                                               \
+            return ARGON2_ENCODING_FAIL;                                       \
+        }                                                                      \
+        memcpy(dst, str, pp_len + 1);                                          \
+        dst += pp_len;                                                         \
+        dst_len -= pp_len;                                                     \
+    } while ((void)0, 0)
+
+#define SX(x)                                                                  \
+    do {                                                                       \
+        char tmp[30];                                                          \
+        sprintf(tmp, "%lu", (unsigned long)(x));                               \
+        SS(tmp);                                                               \
+    } while ((void)0, 0)
+
+#define SB(buf, len)                                                           \
+    do {                                                                       \
+        size_t sb_len = to_base64(dst, dst_len, buf, len);                     \
+        if (sb_len == (size_t)-1) {                                            \
+            return ARGON2_ENCODING_FAIL;                                       \
+        }                                                                      \
+        dst += sb_len;                                                         \
+        dst_len -= sb_len;                                                     \
+    } while ((void)0, 0)
+
+    const char* type_string = argon2_type2string(type, 0);
+    int validation_result = validate_inputs(ctx);
+
+    if (!type_string) {
+      return ARGON2_ENCODING_FAIL;
+    }
+
+    if (validation_result != ARGON2_OK) {
+      return validation_result;
+    }
+
+
+    SS("$");
+    SS(type_string);
+
+    SS("$v=");
+    SX(ctx->version);
+
+    SS("$m=");
+    SX(ctx->m_cost);
+    SS(",t=");
+    SX(ctx->t_cost);
+    SS(",p=");
+    SX(ctx->lanes);
+
+    SS("$");
+    SB(ctx->salt, ctx->saltlen);
+
+    SS("$");
+    SB(ctx->out, ctx->outlen);
+    return ARGON2_OK;
+
+#undef SS
+#undef SX
+#undef SB
+}
+
+size_t b64len(uint32_t len) {
+    size_t olen = ((size_t)len / 3) << 2;
+
+    switch (len % 3) {
+    case 2:
+        olen++;
+    /* fall through */
+    case 1:
+        olen += 2;
+        break;
+    }
+
+    return olen;
+}
+
+size_t numlen(uint32_t num) {
+    size_t len = 1;
+    while (num >= 10) {
+        ++len;
+        num = num / 10;
+    }
+    return len;
+}
+

+ 437 - 0
Sources/Argon2/include/argon2.h

@@ -0,0 +1,437 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ARGON2_H
+#define ARGON2_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Symbols visibility control */
+#ifdef A2_VISCTL
+#define ARGON2_PUBLIC __attribute__((visibility("default")))
+#define ARGON2_LOCAL __attribute__ ((visibility ("hidden")))
+#elif _MSC_VER
+#define ARGON2_PUBLIC __declspec(dllexport)
+#define ARGON2_LOCAL
+#else
+#define ARGON2_PUBLIC
+#define ARGON2_LOCAL
+#endif
+
+/*
+ * Argon2 input parameter restrictions
+ */
+
+/* Minimum and maximum number of lanes (degree of parallelism) */
+#define ARGON2_MIN_LANES UINT32_C(1)
+#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
+
+/* Minimum and maximum number of threads */
+#define ARGON2_MIN_THREADS UINT32_C(1)
+#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
+
+/* Number of synchronization points between lanes per pass */
+#define ARGON2_SYNC_POINTS UINT32_C(4)
+
+/* Minimum and maximum digest size in bytes */
+#define ARGON2_MIN_OUTLEN UINT32_C(4)
+#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
+#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
+
+#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
+/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */
+#define ARGON2_MAX_MEMORY_BITS                                                 \
+    ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
+#define ARGON2_MAX_MEMORY                                                      \
+    ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
+
+/* Minimum and maximum number of passes */
+#define ARGON2_MIN_TIME UINT32_C(1)
+#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum password length in bytes */
+#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
+#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum associated data length in bytes */
+#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
+#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum salt length in bytes */
+#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
+#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum key length in bytes */
+#define ARGON2_MIN_SECRET UINT32_C(0)
+#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
+
+/* Flags to determine which fields are securely wiped (default = no wipe). */
+#define ARGON2_DEFAULT_FLAGS UINT32_C(0)
+#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
+#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
+
+/* Global flag to determine if we are wiping internal memory buffers. This flag
+ * is defined in core.c and defaults to 1 (wipe internal memory). */
+extern int FLAG_clear_internal_memory;
+
+/* Error codes */
+typedef enum Argon2_ErrorCodes {
+    ARGON2_OK = 0,
+
+    ARGON2_OUTPUT_PTR_NULL = -1,
+
+    ARGON2_OUTPUT_TOO_SHORT = -2,
+    ARGON2_OUTPUT_TOO_LONG = -3,
+
+    ARGON2_PWD_TOO_SHORT = -4,
+    ARGON2_PWD_TOO_LONG = -5,
+
+    ARGON2_SALT_TOO_SHORT = -6,
+    ARGON2_SALT_TOO_LONG = -7,
+
+    ARGON2_AD_TOO_SHORT = -8,
+    ARGON2_AD_TOO_LONG = -9,
+
+    ARGON2_SECRET_TOO_SHORT = -10,
+    ARGON2_SECRET_TOO_LONG = -11,
+
+    ARGON2_TIME_TOO_SMALL = -12,
+    ARGON2_TIME_TOO_LARGE = -13,
+
+    ARGON2_MEMORY_TOO_LITTLE = -14,
+    ARGON2_MEMORY_TOO_MUCH = -15,
+
+    ARGON2_LANES_TOO_FEW = -16,
+    ARGON2_LANES_TOO_MANY = -17,
+
+    ARGON2_PWD_PTR_MISMATCH = -18,    /* NULL ptr with non-zero length */
+    ARGON2_SALT_PTR_MISMATCH = -19,   /* NULL ptr with non-zero length */
+    ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
+    ARGON2_AD_PTR_MISMATCH = -21,     /* NULL ptr with non-zero length */
+
+    ARGON2_MEMORY_ALLOCATION_ERROR = -22,
+
+    ARGON2_FREE_MEMORY_CBK_NULL = -23,
+    ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
+
+    ARGON2_INCORRECT_PARAMETER = -25,
+    ARGON2_INCORRECT_TYPE = -26,
+
+    ARGON2_OUT_PTR_MISMATCH = -27,
+
+    ARGON2_THREADS_TOO_FEW = -28,
+    ARGON2_THREADS_TOO_MANY = -29,
+
+    ARGON2_MISSING_ARGS = -30,
+
+    ARGON2_ENCODING_FAIL = -31,
+
+    ARGON2_DECODING_FAIL = -32,
+
+    ARGON2_THREAD_FAIL = -33,
+
+    ARGON2_DECODING_LENGTH_FAIL = -34,
+
+    ARGON2_VERIFY_MISMATCH = -35
+} argon2_error_codes;
+
+/* Memory allocator types --- for external allocation */
+typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
+typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
+
+/* Argon2 external data structures */
+
+/*
+ *****
+ * Context: structure to hold Argon2 inputs:
+ *  output array and its length,
+ *  password and its length,
+ *  salt and its length,
+ *  secret and its length,
+ *  associated data and its length,
+ *  number of passes, amount of used memory (in KBytes, can be rounded up a bit)
+ *  number of parallel threads that will be run.
+ * All the parameters above affect the output hash value.
+ * Additionally, two function pointers can be provided to allocate and
+ * deallocate the memory (if NULL, memory will be allocated internally).
+ * Also, three flags indicate whether to erase password, secret as soon as they
+ * are pre-hashed (and thus not needed anymore), and the entire memory
+ *****
+ * Simplest situation: you have output array out[8], password is stored in
+ * pwd[32], salt is stored in salt[16], you do not have keys nor associated
+ * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
+ * 4 parallel lanes.
+ * You want to erase the password, but you're OK with last pass not being
+ * erased. You want to use the default memory allocator.
+ * Then you initialize:
+ Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
+ */
+typedef struct Argon2_Context {
+    uint8_t *out;    /* output array */
+    uint32_t outlen; /* digest length */
+
+    uint8_t *pwd;    /* password array */
+    uint32_t pwdlen; /* password length */
+
+    uint8_t *salt;    /* salt array */
+    uint32_t saltlen; /* salt length */
+
+    uint8_t *secret;    /* key array */
+    uint32_t secretlen; /* key length */
+
+    uint8_t *ad;    /* associated data array */
+    uint32_t adlen; /* associated data length */
+
+    uint32_t t_cost;  /* number of passes */
+    uint32_t m_cost;  /* amount of memory requested (KB) */
+    uint32_t lanes;   /* number of lanes */
+    uint32_t threads; /* maximum number of threads */
+
+    uint32_t version; /* version number */
+
+    allocate_fptr allocate_cbk; /* pointer to memory allocator */
+    deallocate_fptr free_cbk;   /* pointer to memory deallocator */
+
+    uint32_t flags; /* array of bool options */
+} argon2_context;
+
+/* Argon2 primitive type */
+typedef enum Argon2_type {
+  Argon2_d = 0,
+  Argon2_i = 1,
+  Argon2_id = 2
+} argon2_type;
+
+/* Version of the algorithm */
+typedef enum Argon2_version {
+    ARGON2_VERSION_10 = 0x10,
+    ARGON2_VERSION_13 = 0x13,
+    ARGON2_VERSION_NUMBER = ARGON2_VERSION_13
+} argon2_version;
+
+/*
+ * Function that gives the string representation of an argon2_type.
+ * @param type The argon2_type that we want the string for
+ * @param uppercase Whether the string should have the first letter uppercase
+ * @return NULL if invalid type, otherwise the string representation.
+ */
+ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase);
+
+/*
+ * Function that performs memory-hard hashing with certain degree of parallelism
+ * @param  context  Pointer to the Argon2 internal structure
+ * @return Error code if smth is wrong, ARGON2_OK otherwise
+ */
+ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);
+
+/**
+ * Hashes a password with Argon2i, producing an encoded hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hashlen Desired length of the hash in bytes
+ * @param encoded Buffer where to write the encoded hash
+ * @param encodedlen Size of the buffer (thus max size of the encoded hash)
+ * @pre   Different parallelism levels will give different results
+ * @pre   Returns ARGON2_OK if successful
+ */
+ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost,
+                                       const uint32_t m_cost,
+                                       const uint32_t parallelism,
+                                       const void *pwd, const size_t pwdlen,
+                                       const void *salt, const size_t saltlen,
+                                       const size_t hashlen, char *encoded,
+                                       const size_t encodedlen);
+
+/**
+ * Hashes a password with Argon2i, producing a raw hash at @hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hash Buffer where to write the raw hash - updated by the function
+ * @param hashlen Desired length of the hash in bytes
+ * @pre   Different parallelism levels will give different results
+ * @pre   Returns ARGON2_OK if successful
+ */
+ARGON2_PUBLIC int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+                                   const uint32_t parallelism, const void *pwd,
+                                   const size_t pwdlen, const void *salt,
+                                   const size_t saltlen, void *hash,
+                                   const size_t hashlen);
+
+ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,
+                                       const uint32_t m_cost,
+                                       const uint32_t parallelism,
+                                       const void *pwd, const size_t pwdlen,
+                                       const void *salt, const size_t saltlen,
+                                       const size_t hashlen, char *encoded,
+                                       const size_t encodedlen);
+
+ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+                                   const uint32_t parallelism, const void *pwd,
+                                   const size_t pwdlen, const void *salt,
+                                   const size_t saltlen, void *hash,
+                                   const size_t hashlen);
+
+ARGON2_PUBLIC int argon2id_hash_encoded(const uint32_t t_cost,
+                                        const uint32_t m_cost,
+                                        const uint32_t parallelism,
+                                        const void *pwd, const size_t pwdlen,
+                                        const void *salt, const size_t saltlen,
+                                        const size_t hashlen, char *encoded,
+                                        const size_t encodedlen);
+
+ARGON2_PUBLIC int argon2id_hash_raw(const uint32_t t_cost,
+                                    const uint32_t m_cost,
+                                    const uint32_t parallelism, const void *pwd,
+                                    const size_t pwdlen, const void *salt,
+                                    const size_t saltlen, void *hash,
+                                    const size_t hashlen);
+
+/* generic function underlying the above ones */
+ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
+                              const uint32_t parallelism, const void *pwd,
+                              const size_t pwdlen, const void *salt,
+                              const size_t saltlen, void *hash,
+                              const size_t hashlen, char *encoded,
+                              const size_t encodedlen, argon2_type type,
+                              const uint32_t version);
+
+/**
+ * Verifies a password against an encoded string
+ * Encoded string is restricted as in validate_inputs()
+ * @param encoded String encoding parameters, salt, hash
+ * @param pwd Pointer to password
+ * @pre   Returns ARGON2_OK if successful
+ */
+ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd,
+                                 const size_t pwdlen);
+
+ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,
+                                 const size_t pwdlen);
+
+ARGON2_PUBLIC int argon2id_verify(const char *encoded, const void *pwd,
+                                  const size_t pwdlen);
+
+/* generic function underlying the above ones */
+ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,
+                                const size_t pwdlen, argon2_type type);
+
+/**
+ * Argon2d: Version of Argon2 that picks memory blocks depending
+ * on the password and salt. Only for side-channel-free
+ * environment!!
+ *****
+ * @param  context  Pointer to current Argon2 context
+ * @return  Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
+
+/**
+ * Argon2i: Version of Argon2 that picks memory blocks
+ * independent on the password and salt. Good for side-channels,
+ * but worse w.r.t. tradeoff attacks if only one pass is used.
+ *****
+ * @param  context  Pointer to current Argon2 context
+ * @return  Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2i_ctx(argon2_context *context);
+
+/**
+ * Argon2id: Version of Argon2 where the first half-pass over memory is
+ * password-independent, the rest are password-dependent (on the password and
+ * salt). OK against side channels (they reduce to 1/2-pass Argon2i), and
+ * better with w.r.t. tradeoff attacks (similar to Argon2d).
+ *****
+ * @param  context  Pointer to current Argon2 context
+ * @return  Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2id_ctx(argon2_context *context);
+
+/**
+ * Verify if a given password is correct for Argon2d hashing
+ * @param  context  Pointer to current Argon2 context
+ * @param  hash  The password hash to verify. The length of the hash is
+ * specified by the context outlen member
+ * @return  Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);
+
+/**
+ * Verify if a given password is correct for Argon2i hashing
+ * @param  context  Pointer to current Argon2 context
+ * @param  hash  The password hash to verify. The length of the hash is
+ * specified by the context outlen member
+ * @return  Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash);
+
+/**
+ * Verify if a given password is correct for Argon2id hashing
+ * @param  context  Pointer to current Argon2 context
+ * @param  hash  The password hash to verify. The length of the hash is
+ * specified by the context outlen member
+ * @return  Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2id_verify_ctx(argon2_context *context,
+                                      const char *hash);
+
+/* generic function underlying the above ones */
+ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,
+                                    argon2_type type);
+
+/**
+ * Get the associated error message for given error code
+ * @return  The error message associated with the given error code
+ */
+ARGON2_PUBLIC const char *argon2_error_message(int error_code);
+
+/**
+ * Returns the encoded hash length for the given input parameters
+ * @param t_cost  Number of iterations
+ * @param m_cost  Memory usage in kibibytes
+ * @param parallelism  Number of threads; used to compute lanes
+ * @param saltlen  Salt size in bytes
+ * @param hashlen  Hash size in bytes
+ * @param type The argon2_type that we want the encoded length for
+ * @return  The encoded hash length in bytes
+ */
+ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
+                                       uint32_t parallelism, uint32_t saltlen,
+                                       uint32_t hashlen, argon2_type type);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

+ 156 - 0
Sources/Argon2/include/blake2/blake2-impl.h

@@ -0,0 +1,156 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef PORTABLE_BLAKE2_IMPL_H
+#define PORTABLE_BLAKE2_IMPL_H
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+#define BLAKE2_INLINE __inline
+#elif defined(__GNUC__) || defined(__clang__)
+#define BLAKE2_INLINE __inline__
+#else
+#define BLAKE2_INLINE
+#endif
+
+/* Argon2 Team - Begin Code */
+/*
+   Not an exhaustive list, but should cover the majority of modern platforms
+   Additionally, the code will always be correct---this is only a performance
+   tweak.
+*/
+#if (defined(__BYTE_ORDER__) &&                                                \
+     (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) ||                           \
+    defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
+    defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) ||       \
+    defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) ||                \
+    defined(_M_ARM)
+#define NATIVE_LITTLE_ENDIAN
+#endif
+/* Argon2 Team - End Code */
+
+static BLAKE2_INLINE uint32_t load32(const void *src) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+    uint32_t w;
+    memcpy(&w, src, sizeof w);
+    return w;
+#else
+    const uint8_t *p = (const uint8_t *)src;
+    uint32_t w = *p++;
+    w |= (uint32_t)(*p++) << 8;
+    w |= (uint32_t)(*p++) << 16;
+    w |= (uint32_t)(*p++) << 24;
+    return w;
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load64(const void *src) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+    uint64_t w;
+    memcpy(&w, src, sizeof w);
+    return w;
+#else
+    const uint8_t *p = (const uint8_t *)src;
+    uint64_t w = *p++;
+    w |= (uint64_t)(*p++) << 8;
+    w |= (uint64_t)(*p++) << 16;
+    w |= (uint64_t)(*p++) << 24;
+    w |= (uint64_t)(*p++) << 32;
+    w |= (uint64_t)(*p++) << 40;
+    w |= (uint64_t)(*p++) << 48;
+    w |= (uint64_t)(*p++) << 56;
+    return w;
+#endif
+}
+
+static BLAKE2_INLINE void store32(void *dst, uint32_t w) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+    memcpy(dst, &w, sizeof w);
+#else
+    uint8_t *p = (uint8_t *)dst;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+#endif
+}
+
+static BLAKE2_INLINE void store64(void *dst, uint64_t w) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+    memcpy(dst, &w, sizeof w);
+#else
+    uint8_t *p = (uint8_t *)dst;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load48(const void *src) {
+    const uint8_t *p = (const uint8_t *)src;
+    uint64_t w = *p++;
+    w |= (uint64_t)(*p++) << 8;
+    w |= (uint64_t)(*p++) << 16;
+    w |= (uint64_t)(*p++) << 24;
+    w |= (uint64_t)(*p++) << 32;
+    w |= (uint64_t)(*p++) << 40;
+    return w;
+}
+
+static BLAKE2_INLINE void store48(void *dst, uint64_t w) {
+    uint8_t *p = (uint8_t *)dst;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+    w >>= 8;
+    *p++ = (uint8_t)w;
+}
+
+static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) {
+    return (w >> c) | (w << (32 - c));
+}
+
+static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
+    return (w >> c) | (w << (64 - c));
+}
+
+void clear_internal_memory(void *v, size_t n);
+
+#endif

+ 89 - 0
Sources/Argon2/include/blake2/blake2.h

@@ -0,0 +1,89 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef PORTABLE_BLAKE2_H
+#define PORTABLE_BLAKE2_H
+
+#include <argon2.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum blake2b_constant {
+    BLAKE2B_BLOCKBYTES = 128,
+    BLAKE2B_OUTBYTES = 64,
+    BLAKE2B_KEYBYTES = 64,
+    BLAKE2B_SALTBYTES = 16,
+    BLAKE2B_PERSONALBYTES = 16
+};
+
+#pragma pack(push, 1)
+typedef struct __blake2b_param {
+    uint8_t digest_length;                   /* 1 */
+    uint8_t key_length;                      /* 2 */
+    uint8_t fanout;                          /* 3 */
+    uint8_t depth;                           /* 4 */
+    uint32_t leaf_length;                    /* 8 */
+    uint64_t node_offset;                    /* 16 */
+    uint8_t node_depth;                      /* 17 */
+    uint8_t inner_length;                    /* 18 */
+    uint8_t reserved[14];                    /* 32 */
+    uint8_t salt[BLAKE2B_SALTBYTES];         /* 48 */
+    uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+} blake2b_param;
+#pragma pack(pop)
+
+typedef struct __blake2b_state {
+    uint64_t h[8];
+    uint64_t t[2];
+    uint64_t f[2];
+    uint8_t buf[BLAKE2B_BLOCKBYTES];
+    unsigned buflen;
+    unsigned outlen;
+    uint8_t last_node;
+} blake2b_state;
+
+/* Ensure param structs have not been wrongly padded */
+/* Poor man's static_assert */
+enum {
+    blake2_size_check_0 = 1 / !!(CHAR_BIT == 8),
+    blake2_size_check_2 =
+        1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)
+};
+
+/* Streaming API */
+ARGON2_LOCAL int blake2b_init(blake2b_state *S, size_t outlen);
+ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
+                     size_t keylen);
+ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
+ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
+ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, size_t outlen);
+
+/* Simple API */
+ARGON2_LOCAL int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
+                         const void *key, size_t keylen);
+
+/* Argon2 Team - Begin Code */
+ARGON2_LOCAL int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
+/* Argon2 Team - End Code */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

+ 471 - 0
Sources/Argon2/include/blake2/blamka-round-opt.h

@@ -0,0 +1,471 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef BLAKE_ROUND_MKA_OPT_H
+#define BLAKE_ROUND_MKA_OPT_H
+
+#include "blake2-impl.h"
+
+#include <emmintrin.h>
+#if defined(__SSSE3__)
+#include <tmmintrin.h> /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */
+#endif
+
+#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
+#include <x86intrin.h>
+#endif
+
+#if !defined(__AVX512F__)
+#if !defined(__AVX2__)
+#if !defined(__XOP__)
+#if defined(__SSSE3__)
+#define r16                                                                    \
+    (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define r24                                                                    \
+    (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define _mm_roti_epi64(x, c)                                                   \
+    (-(c) == 32)                                                               \
+        ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))                      \
+        : (-(c) == 24)                                                         \
+              ? _mm_shuffle_epi8((x), r24)                                     \
+              : (-(c) == 16)                                                   \
+                    ? _mm_shuffle_epi8((x), r16)                               \
+                    : (-(c) == 63)                                             \
+                          ? _mm_xor_si128(_mm_srli_epi64((x), -(c)),           \
+                                          _mm_add_epi64((x), (x)))             \
+                          : _mm_xor_si128(_mm_srli_epi64((x), -(c)),           \
+                                          _mm_slli_epi64((x), 64 - (-(c))))
+#else /* defined(__SSE2__) */
+#define _mm_roti_epi64(r, c)                                                   \
+    _mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
+#endif
+#else
+#endif
+
+static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
+    const __m128i z = _mm_mul_epu32(x, y);
+    return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
+}
+
+#define G1(A0, B0, C0, D0, A1, B1, C1, D1)                                     \
+    do {                                                                       \
+        A0 = fBlaMka(A0, B0);                                                  \
+        A1 = fBlaMka(A1, B1);                                                  \
+                                                                               \
+        D0 = _mm_xor_si128(D0, A0);                                            \
+        D1 = _mm_xor_si128(D1, A1);                                            \
+                                                                               \
+        D0 = _mm_roti_epi64(D0, -32);                                          \
+        D1 = _mm_roti_epi64(D1, -32);                                          \
+                                                                               \
+        C0 = fBlaMka(C0, D0);                                                  \
+        C1 = fBlaMka(C1, D1);                                                  \
+                                                                               \
+        B0 = _mm_xor_si128(B0, C0);                                            \
+        B1 = _mm_xor_si128(B1, C1);                                            \
+                                                                               \
+        B0 = _mm_roti_epi64(B0, -24);                                          \
+        B1 = _mm_roti_epi64(B1, -24);                                          \
+    } while ((void)0, 0)
+
+#define G2(A0, B0, C0, D0, A1, B1, C1, D1)                                     \
+    do {                                                                       \
+        A0 = fBlaMka(A0, B0);                                                  \
+        A1 = fBlaMka(A1, B1);                                                  \
+                                                                               \
+        D0 = _mm_xor_si128(D0, A0);                                            \
+        D1 = _mm_xor_si128(D1, A1);                                            \
+                                                                               \
+        D0 = _mm_roti_epi64(D0, -16);                                          \
+        D1 = _mm_roti_epi64(D1, -16);                                          \
+                                                                               \
+        C0 = fBlaMka(C0, D0);                                                  \
+        C1 = fBlaMka(C1, D1);                                                  \
+                                                                               \
+        B0 = _mm_xor_si128(B0, C0);                                            \
+        B1 = _mm_xor_si128(B1, C1);                                            \
+                                                                               \
+        B0 = _mm_roti_epi64(B0, -63);                                          \
+        B1 = _mm_roti_epi64(B1, -63);                                          \
+    } while ((void)0, 0)
+
+#if defined(__SSSE3__)
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1)                            \
+    do {                                                                       \
+        __m128i t0 = _mm_alignr_epi8(B1, B0, 8);                               \
+        __m128i t1 = _mm_alignr_epi8(B0, B1, 8);                               \
+        B0 = t0;                                                               \
+        B1 = t1;                                                               \
+                                                                               \
+        t0 = C0;                                                               \
+        C0 = C1;                                                               \
+        C1 = t0;                                                               \
+                                                                               \
+        t0 = _mm_alignr_epi8(D1, D0, 8);                                       \
+        t1 = _mm_alignr_epi8(D0, D1, 8);                                       \
+        D0 = t1;                                                               \
+        D1 = t0;                                                               \
+    } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1)                          \
+    do {                                                                       \
+        __m128i t0 = _mm_alignr_epi8(B0, B1, 8);                               \
+        __m128i t1 = _mm_alignr_epi8(B1, B0, 8);                               \
+        B0 = t0;                                                               \
+        B1 = t1;                                                               \
+                                                                               \
+        t0 = C0;                                                               \
+        C0 = C1;                                                               \
+        C1 = t0;                                                               \
+                                                                               \
+        t0 = _mm_alignr_epi8(D0, D1, 8);                                       \
+        t1 = _mm_alignr_epi8(D1, D0, 8);                                       \
+        D0 = t1;                                                               \
+        D1 = t0;                                                               \
+    } while ((void)0, 0)
+#else /* SSE2 */
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1)                            \
+    do {                                                                       \
+        __m128i t0 = D0;                                                       \
+        __m128i t1 = B0;                                                       \
+        D0 = C0;                                                               \
+        C0 = C1;                                                               \
+        C1 = D0;                                                               \
+        D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0));               \
+        D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1));               \
+        B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1));               \
+        B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1));               \
+    } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1)                          \
+    do {                                                                       \
+        __m128i t0, t1;                                                        \
+        t0 = C0;                                                               \
+        C0 = C1;                                                               \
+        C1 = t0;                                                               \
+        t0 = B0;                                                               \
+        t1 = D0;                                                               \
+        B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0));               \
+        B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1));               \
+        D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1));               \
+        D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1));               \
+    } while ((void)0, 0)
+#endif
+
+#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1)                           \
+    do {                                                                       \
+        G1(A0, B0, C0, D0, A1, B1, C1, D1);                                    \
+        G2(A0, B0, C0, D0, A1, B1, C1, D1);                                    \
+                                                                               \
+        DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1);                           \
+                                                                               \
+        G1(A0, B0, C0, D0, A1, B1, C1, D1);                                    \
+        G2(A0, B0, C0, D0, A1, B1, C1, D1);                                    \
+                                                                               \
+        UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1);                         \
+    } while ((void)0, 0)
+#else /* __AVX2__ */
+
+#include <immintrin.h>
+
+#define rotr32(x)   _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
+#define rotr24(x)   _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define rotr16(x)   _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define rotr63(x)   _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
+
+#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do { \
+        __m256i ml = _mm256_mul_epu32(A0, B0); \
+        ml = _mm256_add_epi64(ml, ml); \
+        A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+        D0 = _mm256_xor_si256(D0, A0); \
+        D0 = rotr32(D0); \
+        \
+        ml = _mm256_mul_epu32(C0, D0); \
+        ml = _mm256_add_epi64(ml, ml); \
+        C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+        \
+        B0 = _mm256_xor_si256(B0, C0); \
+        B0 = rotr24(B0); \
+        \
+        ml = _mm256_mul_epu32(A1, B1); \
+        ml = _mm256_add_epi64(ml, ml); \
+        A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+        D1 = _mm256_xor_si256(D1, A1); \
+        D1 = rotr32(D1); \
+        \
+        ml = _mm256_mul_epu32(C1, D1); \
+        ml = _mm256_add_epi64(ml, ml); \
+        C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+        \
+        B1 = _mm256_xor_si256(B1, C1); \
+        B1 = rotr24(B1); \
+    } while((void)0, 0);
+
+#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do { \
+        __m256i ml = _mm256_mul_epu32(A0, B0); \
+        ml = _mm256_add_epi64(ml, ml); \
+        A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+        D0 = _mm256_xor_si256(D0, A0); \
+        D0 = rotr16(D0); \
+        \
+        ml = _mm256_mul_epu32(C0, D0); \
+        ml = _mm256_add_epi64(ml, ml); \
+        C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+        B0 = _mm256_xor_si256(B0, C0); \
+        B0 = rotr63(B0); \
+        \
+        ml = _mm256_mul_epu32(A1, B1); \
+        ml = _mm256_add_epi64(ml, ml); \
+        A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+        D1 = _mm256_xor_si256(D1, A1); \
+        D1 = rotr16(D1); \
+        \
+        ml = _mm256_mul_epu32(C1, D1); \
+        ml = _mm256_add_epi64(ml, ml); \
+        C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+        B1 = _mm256_xor_si256(B1, C1); \
+        B1 = rotr63(B1); \
+    } while((void)0, 0);
+
+#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+        C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+        D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+        \
+        B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+        C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+        D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+    } while((void)0, 0);
+
+#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do { \
+        __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+        __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+        B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+        B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+        \
+        tmp1 = C0; \
+        C0 = C1; \
+        C1 = tmp1; \
+        \
+        tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
+        tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
+        D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+        D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+    } while(0);
+
+#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+        C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+        D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+        \
+        B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+        C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+        D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+    } while((void)0, 0);
+
+#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do { \
+        __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+        __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+        B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+        B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+        \
+        tmp1 = C0; \
+        C0 = C1; \
+        C1 = tmp1; \
+        \
+        tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
+        tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
+        D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+        D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+    } while((void)0, 0);
+
+#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do{ \
+        G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        \
+        DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+        \
+        G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        \
+        UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+    } while((void)0, 0);
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do{ \
+        G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        \
+        DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        \
+        G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+        \
+        UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    } while((void)0, 0);
+
+#endif /* __AVX2__ */
+
+#else /* __AVX512F__ */
+
+#include <immintrin.h>
+
+#define ror64(x, n) _mm512_ror_epi64((x), (n))
+
+static __m512i muladd(__m512i x, __m512i y)
+{
+    __m512i z = _mm512_mul_epu32(x, y);
+    return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
+}
+
+#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        A0 = muladd(A0, B0); \
+        A1 = muladd(A1, B1); \
+\
+        D0 = _mm512_xor_si512(D0, A0); \
+        D1 = _mm512_xor_si512(D1, A1); \
+\
+        D0 = ror64(D0, 32); \
+        D1 = ror64(D1, 32); \
+\
+        C0 = muladd(C0, D0); \
+        C1 = muladd(C1, D1); \
+\
+        B0 = _mm512_xor_si512(B0, C0); \
+        B1 = _mm512_xor_si512(B1, C1); \
+\
+        B0 = ror64(B0, 24); \
+        B1 = ror64(B1, 24); \
+    } while ((void)0, 0)
+
+#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        A0 = muladd(A0, B0); \
+        A1 = muladd(A1, B1); \
+\
+        D0 = _mm512_xor_si512(D0, A0); \
+        D1 = _mm512_xor_si512(D1, A1); \
+\
+        D0 = ror64(D0, 16); \
+        D1 = ror64(D1, 16); \
+\
+        C0 = muladd(C0, D0); \
+        C1 = muladd(C1, D1); \
+\
+        B0 = _mm512_xor_si512(B0, C0); \
+        B1 = _mm512_xor_si512(B1, C1); \
+\
+        B0 = ror64(B0, 63); \
+        B1 = ror64(B1, 63); \
+    } while ((void)0, 0)
+
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+        B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+\
+        C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+        C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+\
+        D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+        D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+    } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+        B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+\
+        C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+        C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+\
+        D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+        D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+    } while ((void)0, 0)
+
+#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
+    do { \
+        G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+        G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+\
+        DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+\
+        G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+        G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+\
+        UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+    } while ((void)0, 0)
+
+#define SWAP_HALVES(A0, A1) \
+    do { \
+        __m512i t0, t1; \
+        t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
+        t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
+        A0 = t0; \
+        A1 = t1; \
+    } while((void)0, 0)
+
+#define SWAP_QUARTERS(A0, A1) \
+    do { \
+        SWAP_HALVES(A0, A1); \
+        A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+        A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+    } while((void)0, 0)
+
+#define UNSWAP_QUARTERS(A0, A1) \
+    do { \
+        A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+        A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+        SWAP_HALVES(A0, A1); \
+    } while((void)0, 0)
+
+#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
+    do { \
+        SWAP_HALVES(A0, B0); \
+        SWAP_HALVES(C0, D0); \
+        SWAP_HALVES(A1, B1); \
+        SWAP_HALVES(C1, D1); \
+        BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+        SWAP_HALVES(A0, B0); \
+        SWAP_HALVES(C0, D0); \
+        SWAP_HALVES(A1, B1); \
+        SWAP_HALVES(C1, D1); \
+    } while ((void)0, 0)
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+    do { \
+        SWAP_QUARTERS(A0, A1); \
+        SWAP_QUARTERS(B0, B1); \
+        SWAP_QUARTERS(C0, C1); \
+        SWAP_QUARTERS(D0, D1); \
+        BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+        UNSWAP_QUARTERS(A0, A1); \
+        UNSWAP_QUARTERS(B0, B1); \
+        UNSWAP_QUARTERS(C0, C1); \
+        UNSWAP_QUARTERS(D0, D1); \
+    } while ((void)0, 0)
+
+#endif /* __AVX512F__ */
+#endif /* BLAKE_ROUND_MKA_OPT_H */

+ 56 - 0
Sources/Argon2/include/blake2/blamka-round-ref.h

@@ -0,0 +1,56 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef BLAKE_ROUND_MKA_H
+#define BLAKE_ROUND_MKA_H
+
+#include "blake2.h"
+#include "blake2-impl.h"
+
+/* designed by the Lyra PHC team */
+static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) {
+    const uint64_t m = UINT64_C(0xFFFFFFFF);
+    const uint64_t xy = (x & m) * (y & m);
+    return x + y + 2 * xy;
+}
+
+#define G(a, b, c, d)                                                          \
+    do {                                                                       \
+        a = fBlaMka(a, b);                                                     \
+        d = rotr64(d ^ a, 32);                                                 \
+        c = fBlaMka(c, d);                                                     \
+        b = rotr64(b ^ c, 24);                                                 \
+        a = fBlaMka(a, b);                                                     \
+        d = rotr64(d ^ a, 16);                                                 \
+        c = fBlaMka(c, d);                                                     \
+        b = rotr64(b ^ c, 63);                                                 \
+    } while ((void)0, 0)
+
+#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,   \
+                           v12, v13, v14, v15)                                 \
+    do {                                                                       \
+        G(v0, v4, v8, v12);                                                    \
+        G(v1, v5, v9, v13);                                                    \
+        G(v2, v6, v10, v14);                                                   \
+        G(v3, v7, v11, v15);                                                   \
+        G(v0, v5, v10, v15);                                                   \
+        G(v1, v6, v11, v12);                                                   \
+        G(v2, v7, v8, v13);                                                    \
+        G(v3, v4, v9, v14);                                                    \
+    } while ((void)0, 0)
+
+#endif

+ 228 - 0
Sources/Argon2/include/core.h

@@ -0,0 +1,228 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ARGON2_CORE_H
+#define ARGON2_CORE_H
+
+#include "argon2.h"
+
+#define CONST_CAST(x) (x)(uintptr_t)
+
+/**********************Argon2 internal constants*******************************/
+
+enum argon2_core_constants {
+    /* Memory block size in bytes */
+    ARGON2_BLOCK_SIZE = 1024,
+    ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
+    ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
+    ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
+    ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
+
+    /* Number of pseudo-random values generated by one call to Blake in Argon2i
+       to
+       generate reference block positions */
+    ARGON2_ADDRESSES_IN_BLOCK = 128,
+
+    /* Pre-hashing digest length and its extension*/
+    ARGON2_PREHASH_DIGEST_LENGTH = 64,
+    ARGON2_PREHASH_SEED_LENGTH = 72
+};
+
+/*************************Argon2 internal data types***********************/
+
+/*
+ * Structure for the (1KB) memory block implemented as 128 64-bit words.
+ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
+ * bounds checking).
+ */
+typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
+
+/*****************Functions that work with the block******************/
+
+/* Initialize each byte of the block with @in */
+void init_block_value(block *b, uint8_t in);
+
+/* Copy block @src to block @dst */
+void copy_block(block *dst, const block *src);
+
+/* XOR @src onto @dst bytewise */
+void xor_block(block *dst, const block *src);
+
+/*
+ * Argon2 instance: memory pointer, number of passes, amount of memory, type,
+ * and derived values.
+ * Used to evaluate the number and location of blocks to construct in each
+ * thread
+ */
+typedef struct Argon2_instance_t {
+    block *memory;          /* Memory pointer */
+    uint32_t version;
+    uint32_t passes;        /* Number of passes */
+    uint32_t memory_blocks; /* Number of blocks in memory */
+    uint32_t segment_length;
+    uint32_t lane_length;
+    uint32_t lanes;
+    uint32_t threads;
+    argon2_type type;
+    int print_internals; /* whether to print the memory blocks */
+    argon2_context *context_ptr; /* points back to original context */
+} argon2_instance_t;
+
+/*
+ * Argon2 position: where we construct the block right now. Used to distribute
+ * work between threads.
+ */
+typedef struct Argon2_position_t {
+    uint32_t pass;
+    uint32_t lane;
+    uint8_t slice;
+    uint32_t index;
+} argon2_position_t;
+
+/*Struct that holds the inputs for thread handling FillSegment*/
+typedef struct Argon2_thread_data {
+    argon2_instance_t *instance_ptr;
+    argon2_position_t pos;
+} argon2_thread_data;
+
+/*************************Argon2 core functions********************************/
+
+/* Allocates memory to the given pointer, uses the appropriate allocator as
+ * specified in the context. Total allocated memory is num*size.
+ * @param context argon2_context which specifies the allocator
+ * @param memory pointer to the pointer to the memory
+ * @param size the size in bytes for each element to be allocated
+ * @param num the number of elements to be allocated
+ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
+ */
+int allocate_memory(const argon2_context *context, uint8_t **memory,
+                    size_t num, size_t size);
+
+/*
+ * Frees memory at the given pointer, uses the appropriate deallocator as
+ * specified in the context. Also cleans the memory using clear_internal_memory.
+ * @param context argon2_context which specifies the deallocator
+ * @param memory pointer to buffer to be freed
+ * @param size the size in bytes for each element to be deallocated
+ * @param num the number of elements to be deallocated
+ */
+void free_memory(const argon2_context *context, uint8_t *memory,
+                 size_t num, size_t size);
+
+/* Function that securely cleans the memory. This ignores any flags set
+ * regarding clearing memory. Usually one just calls clear_internal_memory.
+ * @param mem Pointer to the memory
+ * @param s Memory size in bytes
+ */
+void secure_wipe_memory(void *v, size_t n);
+
+/* Function that securely clears the memory if FLAG_clear_internal_memory is
+ * set. If the flag isn't set, this function does nothing.
+ * @param mem Pointer to the memory
+ * @param s Memory size in bytes
+ */
+void clear_internal_memory(void *v, size_t n);
+
+/*
+ * Computes absolute position of reference block in the lane following a skewed
+ * distribution and using a pseudo-random value as input
+ * @param instance Pointer to the current instance
+ * @param position Pointer to the current position
+ * @param pseudo_rand 32-bit pseudo-random value used to determine the position
+ * @param same_lane Indicates if the block will be taken from the current lane.
+ * If so we can reference the current segment
+ * @pre All pointers must be valid
+ */
+uint32_t index_alpha(const argon2_instance_t *instance,
+                     const argon2_position_t *position, uint32_t pseudo_rand,
+                     int same_lane);
+
+/*
+ * Function that validates all inputs against predefined restrictions and return
+ * an error code
+ * @param context Pointer to current Argon2 context
+ * @return ARGON2_OK if everything is all right, otherwise one of error codes
+ * (all defined in <argon2.h>
+ */
+int validate_inputs(const argon2_context *context);
+
+/*
+ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
+ * password and secret if needed
+ * @param  context  Pointer to the Argon2 internal structure containing memory
+ * pointer, and parameters for time and space requirements.
+ * @param  blockhash Buffer for pre-hashing digest
+ * @param  type Argon2 type
+ * @pre    @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
+ * allocated
+ */
+void initial_hash(uint8_t *blockhash, argon2_context *context,
+                  argon2_type type);
+
+/*
+ * Function creates first 2 blocks per lane
+ * @param instance Pointer to the current instance
+ * @param blockhash Pointer to the pre-hashing digest
+ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
+ */
+void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
+
+/*
+ * Function allocates memory, hashes the inputs with Blake,  and creates first
+ * two blocks. Returns the pointer to the main memory with 2 blocks per lane
+ * initialized
+ * @param  context  Pointer to the Argon2 internal structure containing memory
+ * pointer, and parameters for time and space requirements.
+ * @param  instance Current Argon2 instance
+ * @return Zero if successful, -1 if memory failed to allocate. @context->state
+ * will be modified if successful.
+ */
+int initialize(argon2_instance_t *instance, argon2_context *context);
+
+/*
+ * XORing the last block of each lane, hashing it, making the tag. Deallocates
+ * the memory.
+ * @param context Pointer to current Argon2 context (use only the out parameters
+ * from it)
+ * @param instance Pointer to current instance of Argon2
+ * @pre instance->state must point to necessary amount of memory
+ * @pre context->out must point to outlen bytes of memory
+ * @pre if context->free_cbk is not NULL, it should point to a function that
+ * deallocates memory
+ */
+void finalize(const argon2_context *context, argon2_instance_t *instance);
+
+/*
+ * Function that fills the segment using previous segments also from other
+ * threads
+ * @param context current context
+ * @param instance Pointer to the current instance
+ * @param position Current position
+ * @pre all block pointers must be valid
+ */
+void fill_segment(const argon2_instance_t *instance,
+                  argon2_position_t position);
+
+/*
+ * Function that fills the entire memory t_cost times based on the first two
+ * blocks in each lane
+ * @param instance Pointer to the current instance
+ * @return ARGON2_OK if successful, @context->state
+ */
+int fill_memory_blocks(argon2_instance_t *instance);
+
+#endif

+ 57 - 0
Sources/Argon2/include/encoding.h

@@ -0,0 +1,57 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ENCODING_H
+#define ENCODING_H
+#include "argon2.h"
+
+#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
+#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
+#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
+
+/*
+* encode an Argon2 hash string into the provided buffer. 'dst_len'
+* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
+* is less than the number of required characters (including the
+* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
+*
+* on success, ARGON2_OK is returned.
+*/
+int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
+                  argon2_type type);
+
+/*
+* Decodes an Argon2 hash string into the provided structure 'ctx'.
+* The only fields that must be set prior to this call are ctx.saltlen and
+* ctx.outlen (which must be the maximal salt and out length values that are
+* allowed), ctx.salt and ctx.out (which must be buffers of the specified
+* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
+*
+* Invalid input string causes an error. On success, the ctx is valid and all
+* fields have been initialized.
+*
+* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
+*/
+int decode_string(argon2_context *ctx, const char *str, argon2_type type);
+
+/* Returns the length of the encoded byte stream with length len */
+size_t b64len(uint32_t len);
+
+/* Returns the length of the encoded number num */
+size_t numlen(uint32_t num);
+
+#endif

+ 4 - 0
Sources/Argon2/include/module.modulemap

@@ -0,0 +1,4 @@
+module Argon2 {
+    umbrella header "argon2.h"
+    export *
+}

+ 67 - 0
Sources/Argon2/include/thread.h

@@ -0,0 +1,67 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ARGON2_THREAD_H
+#define ARGON2_THREAD_H
+
+#if !defined(ARGON2_NO_THREADS)
+
+/*
+        Here we implement an abstraction layer for the simpĺe requirements
+        of the Argon2 code. We only require 3 primitives---thread creation,
+        joining, and termination---so full emulation of the pthreads API
+        is unwarranted. Currently we wrap pthreads and Win32 threads.
+
+        The API defines 2 types: the function pointer type,
+   argon2_thread_func_t,
+        and the type of the thread handle---argon2_thread_handle_t.
+*/
+#if defined(_WIN32)
+#include <process.h>
+typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
+typedef uintptr_t argon2_thread_handle_t;
+#else
+#include <pthread.h>
+typedef void *(*argon2_thread_func_t)(void *);
+typedef pthread_t argon2_thread_handle_t;
+#endif
+
+/* Creates a thread
+ * @param handle pointer to a thread handle, which is the output of this
+ * function. Must not be NULL.
+ * @param func A function pointer for the thread's entry point. Must not be
+ * NULL.
+ * @param args Pointer that is passed as an argument to @func. May be NULL.
+ * @return 0 if @handle and @func are valid pointers and a thread is successfully
+ * created.
+ */
+int argon2_thread_create(argon2_thread_handle_t *handle,
+                         argon2_thread_func_t func, void *args);
+
+/* Waits for a thread to terminate
+ * @param handle Handle to a thread created with argon2_thread_create.
+ * @return 0 if @handle is a valid handle, and joining completed successfully.
+*/
+int argon2_thread_join(argon2_thread_handle_t handle);
+
+/* Terminate the current thread. Must be run inside a thread created by
+ * argon2_thread_create.
+*/
+void argon2_thread_exit(void);
+
+#endif /* ARGON2_NO_THREADS */
+#endif

+ 194 - 0
Sources/Argon2/ref.c

@@ -0,0 +1,194 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "argon2.h"
+#include "core.h"
+
+#include "blake2/blamka-round-ref.h"
+#include "blake2/blake2-impl.h"
+#include "blake2/blake2.h"
+
+
+/*
+ * Function fills a new memory block and optionally XORs the old block over the new one.
+ * @next_block must be initialized.
+ * @param prev_block Pointer to the previous block
+ * @param ref_block Pointer to the reference block
+ * @param next_block Pointer to the block to be constructed
+ * @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
+ * @pre all block pointers must be valid
+ */
+static void fill_block(const block *prev_block, const block *ref_block,
+                       block *next_block, int with_xor) {
+    block blockR, block_tmp;
+    unsigned i;
+
+    copy_block(&blockR, ref_block);
+    xor_block(&blockR, prev_block);
+    copy_block(&block_tmp, &blockR);
+    /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */
+    if (with_xor) {
+        /* Saving the next block contents for XOR over: */
+        xor_block(&block_tmp, next_block);
+        /* Now blockR = ref_block + prev_block and
+           block_tmp = ref_block + prev_block + next_block */
+    }
+
+    /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
+       (16,17,..31)... finally (112,113,...127) */
+    for (i = 0; i < 8; ++i) {
+        BLAKE2_ROUND_NOMSG(
+            blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
+            blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
+            blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
+            blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
+            blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
+            blockR.v[16 * i + 15]);
+    }
+
+    /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
+       (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
+    for (i = 0; i < 8; i++) {
+        BLAKE2_ROUND_NOMSG(
+            blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
+            blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
+            blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
+            blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
+            blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
+            blockR.v[2 * i + 113]);
+    }
+
+    copy_block(next_block, &block_tmp);
+    xor_block(next_block, &blockR);
+}
+
+static void next_addresses(block *address_block, block *input_block,
+                           const block *zero_block) {
+    input_block->v[6]++;
+    fill_block(zero_block, input_block, address_block, 0);
+    fill_block(zero_block, address_block, address_block, 0);
+}
+
+void fill_segment(const argon2_instance_t *instance,
+                  argon2_position_t position) {
+    block *ref_block = NULL, *curr_block = NULL;
+    block address_block, input_block, zero_block;
+    uint64_t pseudo_rand, ref_index, ref_lane;
+    uint32_t prev_offset, curr_offset;
+    uint32_t starting_index;
+    uint32_t i;
+    int data_independent_addressing;
+
+    if (instance == NULL) {
+        return;
+    }
+
+    data_independent_addressing =
+        (instance->type == Argon2_i) ||
+        (instance->type == Argon2_id && (position.pass == 0) &&
+         (position.slice < ARGON2_SYNC_POINTS / 2));
+
+    if (data_independent_addressing) {
+        init_block_value(&zero_block, 0);
+        init_block_value(&input_block, 0);
+
+        input_block.v[0] = position.pass;
+        input_block.v[1] = position.lane;
+        input_block.v[2] = position.slice;
+        input_block.v[3] = instance->memory_blocks;
+        input_block.v[4] = instance->passes;
+        input_block.v[5] = instance->type;
+    }
+
+    starting_index = 0;
+
+    if ((0 == position.pass) && (0 == position.slice)) {
+        starting_index = 2; /* we have already generated the first two blocks */
+
+        /* Don't forget to generate the first block of addresses: */
+        if (data_independent_addressing) {
+            next_addresses(&address_block, &input_block, &zero_block);
+        }
+    }
+
+    /* Offset of the current block */
+    curr_offset = position.lane * instance->lane_length +
+                  position.slice * instance->segment_length + starting_index;
+
+    if (0 == curr_offset % instance->lane_length) {
+        /* Last block in this lane */
+        prev_offset = curr_offset + instance->lane_length - 1;
+    } else {
+        /* Previous block */
+        prev_offset = curr_offset - 1;
+    }
+
+    for (i = starting_index; i < instance->segment_length;
+         ++i, ++curr_offset, ++prev_offset) {
+        /*1.1 Rotating prev_offset if needed */
+        if (curr_offset % instance->lane_length == 1) {
+            prev_offset = curr_offset - 1;
+        }
+
+        /* 1.2 Computing the index of the reference block */
+        /* 1.2.1 Taking pseudo-random value from the previous block */
+        if (data_independent_addressing) {
+            if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+                next_addresses(&address_block, &input_block, &zero_block);
+            }
+            pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+        } else {
+            pseudo_rand = instance->memory[prev_offset].v[0];
+        }
+
+        /* 1.2.2 Computing the lane of the reference block */
+        ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+        if ((position.pass == 0) && (position.slice == 0)) {
+            /* Can not reference other lanes yet */
+            ref_lane = position.lane;
+        }
+
+        /* 1.2.3 Computing the number of possible reference block within the
+         * lane.
+         */
+        position.index = i;
+        ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+                                ref_lane == position.lane);
+
+        /* 2 Creating a new block */
+        ref_block =
+            instance->memory + instance->lane_length * ref_lane + ref_index;
+        curr_block = instance->memory + curr_offset;
+        if (ARGON2_VERSION_10 == instance->version) {
+            /* version 1.2.1 and earlier: overwrite, not XOR */
+            fill_block(instance->memory + prev_offset, ref_block, curr_block, 0);
+        } else {
+            if(0 == position.pass) {
+                fill_block(instance->memory + prev_offset, ref_block,
+                           curr_block, 0);
+            } else {
+                fill_block(instance->memory + prev_offset, ref_block,
+                           curr_block, 1);
+            }
+        }
+    }
+}

+ 57 - 0
Sources/Argon2/thread.c

@@ -0,0 +1,57 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#if !defined(ARGON2_NO_THREADS)
+
+#include "thread.h"
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+int argon2_thread_create(argon2_thread_handle_t *handle,
+                         argon2_thread_func_t func, void *args) {
+    if (NULL == handle || func == NULL) {
+        return -1;
+    }
+#if defined(_WIN32)
+    *handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
+    return *handle != 0 ? 0 : -1;
+#else
+    return pthread_create(handle, NULL, func, args);
+#endif
+}
+
+int argon2_thread_join(argon2_thread_handle_t handle) {
+#if defined(_WIN32)
+    if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
+        return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
+    }
+    return -1;
+#else
+    return pthread_join(handle, NULL);
+#endif
+}
+
+void argon2_thread_exit(void) {
+#if defined(_WIN32)
+    _endthreadex(0);
+#else
+    pthread_exit(NULL);
+#endif
+}
+
+#endif /* ARGON2_NO_THREADS */

+ 234 - 0
Sources/Binary/Bytes.swift

@@ -0,0 +1,234 @@
+// Bytes.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public func lenght<T>(_ bytes: Bytes) -> T where T: BinaryInteger {
+    return T(bytes.rawValue.count)
+}
+
+public struct Bytes: RawRepresentable {
+
+    public var rawValue: [UInt8]
+
+    public var lenght: Int {
+        rawValue.count
+    }
+
+    public var data: Data {
+        Data(rawValue)
+    }
+
+    public var hexa: String {
+        rawValue.map { .init(format: "%02x", $0) }.joined()
+    }
+
+    public init() {
+        rawValue = []
+    }
+
+    public init(rawValue: [UInt8]) {
+        self.rawValue = [UInt8](rawValue)
+    }
+
+    public init(_ buffer: UnsafeRawBufferPointer) {
+        rawValue = Array(buffer)
+    }
+
+    public init(slice: ArraySlice<UInt8>) {
+        self.rawValue = [UInt8](slice)
+    }
+
+    public init(lenght: Int) {
+        self.init(rawValue: [UInt8](repeating: 0, count: lenght))
+    }
+
+    public init(repeating: UInt8, count: Int) {
+        self.init(rawValue: [UInt8](repeating: repeating, count: count))
+    }
+
+    public init(random lenght: Int) throws {
+        self.rawValue = (0..<lenght).map { _ in 
+            UInt8.random(in: UInt8.min...UInt8.max)
+        }
+    }
+
+    public init(data: Data) {
+        self.rawValue = data.withUnsafeBytes { Array($0) }
+    }
+
+    public init(contentsOf url: URL) throws {
+        let data = try Data(contentsOf: url)
+        self.init(data: data)
+    }
+
+    public init?(string: String, using encoding: String.Encoding) {
+        guard let data = string.data(using: encoding) else { return nil }
+        self.init(data: data)
+    }
+
+    public init?(base64Encoded: String) {
+        guard let data = Data(base64Encoded: base64Encoded) else { return nil }
+        self.init(data: data)
+    }
+
+    public init?(hex: String) {
+        let utf8 = [UInt8](hex.utf8)
+        let offset = hex.hasPrefix("0x") ? 2 : 0
+        var array = [UInt8]()
+
+        let start = utf8.startIndex.advanced(by: offset)
+        let end = utf8.endIndex
+        let step = utf8.startIndex.advanced(by: 2)
+
+        for index in stride(from: start, to: end, by: step) {
+            let hex = "\( UnicodeScalar(utf8[index]) )\( UnicodeScalar(utf8[index.advanced(by: 1)]) )"
+            guard let byte = UInt8(hex, radix: 16) else { return nil }
+            array.append(byte)
+        }
+
+        rawValue = array
+    }
+
+    public subscript (index: Int) -> UInt8 {
+        get { return rawValue[index] }
+        set { rawValue[index] = newValue }
+    }
+
+    public subscript (range: CountableRange<Int>) -> Bytes {
+        return Bytes(slice: rawValue[range])
+    }
+
+    public mutating func append(_ byte: UInt8) {
+        rawValue.append(byte)
+    }
+
+    public mutating func append(_ bytes: Array<UInt8>) {
+        rawValue.append(contentsOf: bytes)
+    }
+
+    public mutating func append(_ bytes: Bytes) {
+        rawValue.append(contentsOf: bytes.rawValue)
+    }
+
+    @discardableResult
+    public func withBytes<T>(_ body: ([UInt8]) -> T) -> T {
+        return body(rawValue)
+    }
+
+    @discardableResult
+    public mutating func withMutableBytes<T>(_ body: (inout [UInt8]) -> T) -> T {
+        return body(&rawValue)
+    }
+
+    public func map<T>() -> [T] where T: BinaryInteger {
+        return map { T($0) }
+    }
+
+    public static func + (lhs: Bytes, rhs: Bytes) -> Bytes {
+        return Bytes(rawValue: lhs.rawValue + rhs.rawValue)
+    }
+
+    public static func += (lhs: inout Bytes, rhs: Bytes) {
+        lhs = Bytes(rawValue: lhs.rawValue + rhs.rawValue)
+    }
+
+    public static func + (lhs: Bytes, rhs: UInt8) -> Bytes {
+        return Bytes(rawValue: lhs.rawValue + [rhs])
+    }
+
+    public static func += (lhs: inout Bytes, rhs: UInt8) {
+        lhs.append(rhs)
+    }
+
+}
+
+extension Bytes: Sequence {
+
+    /// Returns an iterator over the elements of this sequence.
+    public func makeIterator() -> IndexingIterator<[UInt8]> {
+        rawValue.makeIterator()
+    }
+
+    /// A value less than or equal to the number of elements in the sequence,
+    /// calculated nondestructively.
+    ///
+    /// The default implementation returns 0. If you provide your own
+    /// implementation, make sure to compute the value nondestructively.
+    ///
+    /// - Complexity: O(1), except if the sequence also conforms to `Collection`.
+    ///   In this case, see the documentation of `Collection.underestimatedCount`.
+    public var underestimatedCount: Int {
+        return rawValue.underestimatedCount
+    }
+
+    /// Call `body(p)`, where `p` is a pointer to the collection's
+    /// contiguous storage.  If no such storage exists, it is
+    /// first created.  If the collection does not support an internal
+    /// representation in a form of contiguous storage, `body` is not
+    /// called and `nil` is returned.
+    ///
+    /// A `Collection` that provides its own implementation of this method
+    /// must also guarantee that an equivalent buffer of its `SubSequence`
+    /// can be generated by advancing the pointer by the distance to the
+    /// slice's `startIndex`.
+    public func withContiguousStorageIfAvailable<R>(_ body: (UnsafeBufferPointer<UInt8>) throws -> R) rethrows -> R? {
+        return try rawValue.withContiguousStorageIfAvailable(body)
+    }
+
+}
+
+extension Bytes: ExpressibleByArrayLiteral {
+
+    public init(arrayLiteral elements: UInt8...) {
+        rawValue = elements
+    }
+}
+
+extension Bytes: ContiguousBytes {
+
+    /// Calls the given closure with the contents of underlying storage.
+    ///
+    /// - note: Calling `withUnsafeBytes` multiple times does not guarantee that
+    ///         the same buffer pointer will be passed in every time.
+    /// - warning: The buffer argument to the body should not be stored or used
+    ///            outside of the lifetime of the call to the closure.
+    public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
+        return try rawValue.withUnsafeBytes(body)
+    }
+
+    public mutating func withUnsafeMutableBytes<T>(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T {
+        return try rawValue.withUnsafeMutableBytes(body)
+    }
+}
+
+extension Bytes: DataProtocol {
+
+    public var regions: CollectionOfOne<[UInt8]> {
+        rawValue.regions
+    }
+
+    public var startIndex: Int {
+        rawValue.startIndex
+    }
+
+    public var endIndex: Int {
+        rawValue.endIndex
+    }
+
+}

+ 181 - 0
Sources/Binary/BytesRepresentable.swift

@@ -0,0 +1,181 @@
+// BytesRepresentable.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+// MARK: - Bytes Representatble Protocol
+
+public protocol BytesRepresentable {
+
+    init(_ bytes: Bytes) throws
+
+    var bytes: Bytes { get }
+}
+
+// MARK: - Streamable Boolean Bytes
+
+extension Bool: BytesRepresentable {
+
+    public init(_ bytes: Bytes) throws {
+        guard bytes.lenght == MemoryLayout<Self>.size else { throw BinaryError.invalidLenght }
+        self = bytes.withUnsafeBytes { $0.load(as: Self.self) }
+    }
+
+    public var bytes: Bytes {
+        withUnsafeBytes(of: self) { Bytes($0) }
+    }
+
+}
+
+// MARK: - Streamable Integer
+
+extension BytesRepresentable where Self: BinaryInteger {
+
+    public init(_ bytes: Bytes) throws {
+        guard bytes.lenght == MemoryLayout<Self>.size else { throw BinaryError.invalidLenght }
+        self = bytes.withUnsafeBytes { $0.load(as: Self.self) }
+    }
+
+    public var bytes: Bytes {
+        withUnsafeBytes(of: self) { Bytes($0) }
+    }
+
+}
+
+extension Int: BytesRepresentable { }
+
+extension Int8: BytesRepresentable { }
+
+extension Int16: BytesRepresentable { }
+
+extension Int32: BytesRepresentable { }
+
+extension Int64: BytesRepresentable { }
+
+extension UInt: BytesRepresentable { }
+
+extension UInt8: BytesRepresentable { }
+
+extension UInt16: BytesRepresentable { }
+
+extension UInt32: BytesRepresentable { }
+
+extension UInt64: BytesRepresentable { }
+
+// MARK: - Streamable Floating Point
+
+extension BytesRepresentable where Self: FloatingPoint {
+
+    public init(_ bytes: Bytes) throws {
+        guard bytes.lenght == MemoryLayout<Self>.size else { throw BinaryError.invalidLenght }
+        self = bytes.withUnsafeBytes { $0.load(as: Self.self) }
+    }
+
+    public var bytes: Bytes {
+        withUnsafeBytes(of: self) { Bytes(rawValue: Array($0)) }
+    }
+
+}
+
+extension Double: BytesRepresentable { }
+
+extension Float: BytesRepresentable { }
+
+// MARK: - RawRepresentable Bytes
+
+extension BytesRepresentable where Self: RawRepresentable, RawValue: BytesRepresentable {
+
+    public init(_ bytes: Bytes) throws {
+        let rawValue = try RawValue(bytes)
+        guard let value = Self(rawValue: rawValue) else { throw BinaryError.invalidValue }
+        self = value
+    }
+
+    public var bytes: Bytes { rawValue.bytes }
+}
+
+// MARK: - Bytes
+
+extension Bytes: BytesRepresentable {
+
+    public init(_ bytes: Bytes) throws {
+        self = bytes
+    }
+
+    public var bytes: Bytes { self }
+}
+
+// MARK: - Bytes Array
+
+extension Array where Element == Bytes {
+
+    subscript<T>(_ index: Int) -> T? where T: BytesRepresentable {
+        return try? T(self[index])
+    }
+}
+
+// MARK: - Bytes Dictionary
+
+extension Dictionary where Value == Bytes {
+
+    subscript<T>(_ key: Key) -> T? where T: BytesRepresentable {
+        guard let bytes = self[key] else { return nil }
+        return try? T(bytes)
+    }
+}
+
+// MARK: - String Bytes
+
+extension String: BytesRepresentable {
+
+    public var bytes: Bytes { bytes(using: .utf8) ?? [] }
+
+    public init(_ bytes: Bytes) throws {
+        guard let string = String(bytes: bytes, encoding: .utf8) else { throw BinaryError.invalidValue }
+        self = string
+    }
+
+}
+
+// MARK: - Data Bytes
+
+extension Data: BytesRepresentable {
+
+    public var bytes: Bytes { Bytes(data: self) }
+
+    public init(_ bytes: Bytes) throws {
+        self = Data(bytes.rawValue)
+    }
+
+}
+
+// MARK: - UUID Bytes
+
+extension UUID: BytesRepresentable {
+
+    public var bytes: Bytes {
+        withUnsafeBytes(of: uuid) { Bytes($0) }
+    }
+
+    public init(_ bytes: Bytes) throws {
+        guard bytes.lenght == MemoryLayout<uuid_t>.size else { throw BinaryError.invalidLenght }
+        let uuid = bytes.withUnsafeBytes { $0.load(as: uuid_t.self) }
+        self = UUID(uuid: uuid)
+    }
+
+}

+ 24 - 0
Sources/Binary/Error.swift

@@ -0,0 +1,24 @@
+// Error.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public enum BinaryError: Error {
+    case invalidValue
+    case invalidLenght
+}

+ 74 - 0
Sources/Binary/Input.swift

@@ -0,0 +1,74 @@
+// Input.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public class Input {
+
+    public let bytes: Bytes
+
+    public private(set) var offset = 0
+
+    public var remaining: Bytes {
+        bytes.suffix(from: offset)
+    }
+
+    private let stream: InputStream
+
+    public init(bytes: Bytes) {
+        self.bytes = bytes
+
+        let data = Data(bytes.rawValue)
+        stream = InputStream(data: data)
+        stream.open()
+    }
+
+    deinit {
+        stream.close()
+    }
+
+    public func read(lenght: Int) throws -> Bytes {
+        var out = Bytes(lenght: lenght)
+        let count = stream.read(&out.rawValue, maxLength: lenght)
+        if let error = stream.streamError { throw error }
+        offset += count
+        return out.prefix(count)
+    }
+
+    public func read<T>(lenght: Int) throws -> T where T: BytesRepresentable {
+        let bytes = try read(lenght: lenght)
+        return try T(bytes)
+    }
+
+    public func read<T>() throws -> T where T: Readable {
+        return try T(from: self)
+    }
+
+    public func read<T>(maxLenght: Int) throws -> [T] where T: Readable {
+        var array = [T]()
+
+        var count = 0
+        while count < maxLenght {
+            array.append(try read() as T)
+            count += 1
+        }
+
+        return array
+    }
+
+}

+ 57 - 0
Sources/Binary/Output.swift

@@ -0,0 +1,57 @@
+// Output.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public class Output {
+
+    public var bytes: Bytes? {
+        guard let data = stream.property(forKey: .dataWrittenToMemoryStreamKey) as? Data else { return nil }
+        return Bytes(data: data)
+    }
+
+    public private(set) var lenght = 0
+
+    private let stream: OutputStream
+
+    public init() {
+        stream = OutputStream.toMemory()
+        stream.open()
+    }
+
+    public init?(url: URL, append: Bool = false) {
+        guard let stream = OutputStream(url: url, append: append) else { return nil }
+        self.stream = stream
+        self.stream.open()
+    }
+
+    deinit {
+        stream.close()
+    }
+
+    public func write(_ bytes: Bytes) throws {
+        let count = stream.write(bytes.rawValue, maxLength: bytes.lenght)
+        if let error = stream.streamError { throw error }
+        lenght += count
+    }
+
+    public func write<T>(_ value: T) throws where T: Writable {
+        try value.write(to: self)
+    }
+
+}

+ 188 - 0
Sources/Binary/Streamable.swift

@@ -0,0 +1,188 @@
+// Streamable.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+/// A type that can write itself to a binary output.
+public protocol Writable {
+
+    /// Writes this value into the given output.
+    ///
+    /// This function throws an error if any values are invalid for the given format.
+    ///
+    /// - Parameter output: The output stream to write data to.
+    func write(to output: Output) throws
+}
+
+/// A type that can read itself from an binary input.
+public protocol Readable {
+
+    /// Creates a new instance by reading from the input stream.
+    ///
+    /// This initializer throws an error if reading from the input fails, or
+    /// if the data read is corrupted or otherwise invalid.
+    ///
+    /// - Parameter input: The input stream to read data from.
+    init(from input: Input) throws
+}
+
+/// A type that can convert itself into and out of a binary stream.
+///
+/// `Binary` is a type alias for the `Writable` and `Readable` protocols.
+/// When you use `Binary` as a type or a generic constraint, it matches
+/// any type that conforms to both protocols.
+public typealias Streamable = Readable & Writable
+
+extension Readable where Self: BytesRepresentable {
+
+    public init(from input: Input) throws {
+        let bytes = try input.read(lenght: MemoryLayout<Self>.size)
+        self = try Self(bytes)
+    }
+
+}
+
+extension Writable where Self: BytesRepresentable {
+
+    public func write(to output: Output) throws {
+        try output.write(bytes)
+    }
+
+}
+
+// MARK: - Streamable Boolean
+
+extension Bool: Streamable { }
+
+// MARK: - Streamable Integer
+
+extension Int: Streamable { }
+
+extension Int8: Streamable { }
+
+extension Int16: Streamable { }
+
+extension Int32: Streamable { }
+
+extension Int64: Streamable { }
+
+extension UInt: Streamable { }
+
+extension UInt8: Streamable { }
+
+extension UInt16: Streamable { }
+
+extension UInt32: Streamable { }
+
+extension UInt64: Streamable { }
+
+// MARK: - Streamable Floating Point
+
+extension Double: Streamable { }
+
+extension Float: Streamable { }
+
+// MARK: - Streamable RawRepresentable
+
+extension Readable where Self: RawRepresentable, RawValue: Readable {
+
+    public init(from input: Input) throws {
+        let rawValue = try RawValue(from: input)
+        guard let value = Self(rawValue: rawValue) else { throw BinaryError.invalidValue }
+        self = value
+    }
+
+}
+
+extension Writable where Self: RawRepresentable, RawValue: Writable {
+
+    public func write(to output: Output) throws {
+        try output.write(rawValue)
+    }
+}
+
+// MARK: - Readable OptionSet
+
+extension Readable where Self: OptionSet, RawValue: Readable {
+
+    public init(from input: Input) throws {
+        let rawValue = try RawValue(from: input)
+        self = Self(rawValue: rawValue)
+    }
+
+}
+
+// MARK: - Writable Array
+
+extension Array: Writable where Element: Writable {
+
+    public func write(to output: Output) throws {
+        try forEach { try output.write($0) }
+    }
+
+}
+
+// MARK: - Streamable String
+
+extension String: Streamable {
+
+    public init?(bytes: Bytes, encoding: String.Encoding) {
+        let data = Data(bytes.rawValue)
+        self.init(data: data, encoding: encoding)
+    }
+
+    public func bytes(using: String.Encoding) -> Bytes? {
+        return data(using: .utf8)?.bytes
+    }
+
+}
+
+// MARK: - Streamable Data
+
+extension Data: Streamable {
+
+    public init(from input: Input) throws {
+        let bytes = try input.read() as Bytes
+        self = Data(bytes.rawValue)
+    }
+
+    public func write(to output: Output) throws {
+        let bytes = Bytes(data: self)
+        try output.write(bytes)
+    }
+
+}
+
+// MARK: - Streamable UUID
+
+extension UUID: Streamable { }
+
+// MARK: - Streamable Bytes
+
+extension Bytes: Streamable {
+
+    public init(from input: Input) throws {
+        self = try input.read(lenght: input.remaining.count)
+    }
+
+    public func write(to output: Output) throws {
+        try output.write(self)
+    }
+
+}
+

+ 68 - 0
Sources/Binary/TLV.swift

@@ -0,0 +1,68 @@
+// TLV.swift
+// This file is part of MiKee.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// MiKee 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 3 of the License, or
+// (at your option) any later version.
+//
+// MiKee 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 MiKee. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public struct TLV<Type, Lenght> where Lenght: BinaryInteger {
+
+    public let type: Type
+
+    public var value: Bytes
+
+    public init(type: Type, value: Bytes) {
+        self.type = type
+        self.value = value
+    }
+
+    public func get<T>() throws -> T where T: Readable {
+        let stream = Input(bytes: value)
+        return try stream.read()
+    }
+
+    public mutating func set<T>(_ value: T) throws where T: Writable {
+        self.value = withUnsafeBytes(of: value) { Bytes($0) }
+    }
+}
+
+extension TLV: Readable where Type: Readable, Lenght: Readable {
+
+    public init(from input: Input) throws {
+        type = try input.read()
+        let lenght = try input.read() as Lenght
+        value = try input.read(lenght: Int(lenght))
+    }
+
+}
+
+extension TLV: Writable where Type: Writable, Lenght: Writable {
+
+    public func write(to output: Output) throws {
+        try output.write(type)
+        try output.write(Lenght(value.lenght))
+        try output.write(value)
+    }
+
+}
+
+extension TLV: CustomDebugStringConvertible {
+
+    public var debugDescription: String {
+        "(T:\(type) L:\(value.lenght))"
+    }
+
+}

+ 137 - 0
Sources/Crypto/AES.swift

@@ -0,0 +1,137 @@
+// AES.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import CommonCrypto
+
+public final class AESCipher: Cipher {
+
+    public let key: Bytes
+
+    public let iv: Bytes
+
+    public init(key: Bytes, iv: Bytes) throws {
+
+        guard key.lenght == kCCKeySizeAES256 else {
+            throw CryptoError.keyLenght(expecting: "Equal \(kCCKeySizeAES256)", got: key.lenght)
+        }
+
+        guard iv.lenght == kCCBlockSizeAES128 else {
+            throw CryptoError.ivLenght(expecting: "Equal \(kCCBlockSizeAES128)", got: iv.lenght)
+        }
+
+        self.key = key
+        self.iv = iv
+    }
+
+    public func encrypt(data: Bytes) throws -> Bytes {
+
+        let operation: CCOperation = UInt32(kCCEncrypt)
+        let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES)
+        let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
+
+        var out = Bytes(lenght: data.lenght + kCCBlockSizeAES128)
+        var count: Int = 0
+
+        let status = CCCrypt(operation, algoritm, options,
+                             key.rawValue, key.lenght,
+                             iv.rawValue,
+                             data.rawValue, data.lenght,
+                             &out.rawValue, out.lenght,
+                             &count)
+
+        guard status == kCCSuccess else { throw CryptoError.crypto(status: status) }
+
+        return out.prefix(count)
+    }
+
+    public func decrypt(data: Bytes) throws -> Bytes {
+        guard data.lenght % kCCBlockSizeAES128 == 0 else { throw CryptoError.invalidLenght }
+
+        let operation: CCOperation = UInt32(kCCDecrypt)
+        let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES)
+        let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
+
+        var out = Bytes(lenght: data.lenght)
+        var count: Int = 0
+
+        let status = CCCrypt(operation, algoritm, options,
+                             key.rawValue, key.lenght,
+                             iv.rawValue,
+                             data.rawValue, data.lenght,
+                             &out.rawValue, out.lenght,
+                             &count)
+
+        guard status == kCCSuccess else { throw CryptoError.crypto(status: status) }
+
+        return out.prefix(count)
+    }
+
+}
+
+public final class AESKeyDerivation: KeyDerivation {
+
+    public let seed: Bytes
+
+    public let rounds: UInt64
+
+    public init(seed: Bytes, rounds: UInt64) throws {
+        guard seed.lenght == kCCKeySizeAES256 else { throw CryptoError.invalidLenght }
+        self.seed = seed
+        self.rounds = rounds
+    }
+
+    public func derive(key: Bytes) throws -> Bytes {
+        guard key.lenght == kCCKeySizeAES256 else { throw CryptoError.invalidLenght }
+
+        let cryptor = UnsafeMutablePointer<CCCryptorRef?>.allocate(capacity: 1)
+
+        var status = CCCryptorCreate(CCOperation(kCCEncrypt),
+                                     CCAlgorithm(kCCAlgorithmAES128),
+                                     CCOptions(kCCOptionECBMode),
+                                     key.rawValue,
+                                     key.lenght,
+                                     nil,
+                                     cryptor)
+
+        guard status == kCCSuccess else { throw CryptoError.crypto(status: status) }
+
+        var out = key
+        var count = rounds
+        var dataOutMoved: Int = 0
+
+        while count > 0 {
+            status = CCCryptorUpdate(cryptor.pointee,
+                                     out.rawValue,
+                                     out.lenght,
+                                     &out.rawValue,
+                                     out.lenght,
+                                     &dataOutMoved)
+
+            guard status == kCCSuccess else { throw CryptoError.crypto(status: status) }
+            count -= 1
+        }
+
+        CCCryptorRelease(cryptor.pointee)
+        cryptor.deallocate()
+
+        return SHA256.hash(out)
+    }
+
+}

+ 60 - 0
Sources/Crypto/Argon2.swift

@@ -0,0 +1,60 @@
+// Argon2.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Argon2
+
+public final class Argon2: KeyDerivation {
+
+    public let salt: Bytes
+    public let parallelism: UInt32
+    public let memory: UInt32
+    public let iterations: UInt32
+    public let version: UInt32
+
+    public init(salt: Bytes, parallelism: UInt32, memory: UInt32, iterations: UInt32, version: UInt32) {
+        self.salt = salt
+        self.parallelism = parallelism
+        self.memory = memory
+        self.iterations = iterations
+        self.version = version
+    }
+
+    public func derive(key: Bytes) throws -> Bytes {
+
+        var out = Bytes(lenght: 32)
+        let result = argon2_hash(iterations,
+                                 memory,
+                                 parallelism,
+                                 key.rawValue, key.lenght,
+                                 salt.rawValue, salt.lenght,
+                                 &out.rawValue, out.lenght,
+                                 nil, 0,
+                                 Argon2_d,
+                                 version)
+
+        let code = argon2_error_codes(result)
+
+        guard code == ARGON2_OK else { throw CryptoError.argon(code) }
+
+        return out
+    }
+}
+
+

+ 56 - 0
Sources/Crypto/ChaCha20.swift

@@ -0,0 +1,56 @@
+// ChaCha20.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Sodium
+
+public final class ChaCha20 {
+
+    public let key: Bytes
+
+    public let nonce: Bytes
+
+    public init(key: Bytes, iv nonce: Bytes) throws {
+
+        guard key.lenght == crypto_stream_chacha20_ietf_KEYBYTES else {
+            throw CryptoError.keyLenght(expecting: "Equal \(crypto_stream_chacha20_ietf_KEYBYTES)", got: key.lenght)
+        }
+        
+        guard nonce.lenght == crypto_stream_chacha20_ietf_NONCEBYTES else {
+            throw CryptoError.ivLenght(expecting: "Equal \(crypto_stream_chacha20_ietf_NONCEBYTES)", got: nonce.lenght)
+        }
+
+        self.key = key
+        self.nonce = nonce
+    }
+
+}
+
+extension ChaCha20: Cipher {
+
+    public func encrypt(data: Bytes) throws -> Bytes {
+        var out = Bytes(lenght: lenght(data))
+        crypto_stream_chacha20_ietf_xor(&out.rawValue, data.rawValue, lenght(data), nonce.rawValue, key.rawValue);
+        return out
+    }
+
+    public func decrypt(data: Bytes) throws -> Bytes {
+        return try encrypt(data: data)
+    }
+}

+ 27 - 0
Sources/Crypto/Cipher.swift

@@ -0,0 +1,27 @@
+// Cipher.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+public protocol Cipher {
+
+    func encrypt(data: Bytes) throws -> Bytes
+
+    func decrypt(data: Bytes) throws -> Bytes
+}

+ 30 - 0
Sources/Crypto/Error.swift

@@ -0,0 +1,30 @@
+// Error.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import CommonCrypto
+import Argon2
+
+public enum CryptoError: Error {
+    case keyLenght(expecting: String, got: Int)
+    case ivLenght(expecting: String, got: Int)
+    case crypto(status: CCCryptorStatus)
+    case invalidKey
+    case invalidLenght
+    case argon(argon2_error_codes)
+}

+ 111 - 0
Sources/Crypto/Hash.swift

@@ -0,0 +1,111 @@
+// Hash.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Sodium
+
+public final class SHA256 {
+
+    public static let Lenght = Int(crypto_hash_sha256_BYTES)
+
+    private var state: crypto_hash_sha256_state
+
+    public var final: Bytes {
+        var out = Bytes(lenght: SHA256.Lenght)
+        crypto_hash_sha256_final(&state, &out.rawValue)
+        return out
+    }
+
+    public init() {
+        state = crypto_hash_sha256_state()
+        crypto_hash_sha256_init(&state)
+    }
+
+    public func update(_ bytes: Bytes) {
+        crypto_hash_sha256_update(&state, bytes.rawValue, lenght(bytes));
+    }
+
+    public static func hash(_ bytes: Bytes) -> Bytes {
+        var out = Bytes(lenght: SHA256.Lenght)
+        crypto_hash_sha256(&out.rawValue, bytes.rawValue, lenght(bytes))
+        return out
+    }
+
+}
+
+public final class SHA512 {
+
+    public static let Lenght = Int(crypto_hash_sha512_BYTES)
+
+    private var state: crypto_hash_sha512_state
+
+    public var final: Bytes {
+        var out = Bytes(lenght: SHA512.Lenght)
+        crypto_hash_sha512_final(&state, &out.rawValue)
+        return out
+    }
+
+    public init() {
+        state = crypto_hash_sha512_state()
+        crypto_hash_sha512_init(&state)
+    }
+
+    public func update(_ bytes: Bytes) {
+        crypto_hash_sha512_update(&state, bytes.rawValue, lenght(bytes));
+    }
+
+    public static func hash(_ bytes: Bytes) -> Bytes {
+        var out = Bytes(lenght: SHA512.Lenght)
+        crypto_hash_sha512(&out.rawValue, bytes.rawValue, lenght(bytes))
+        return out
+    }
+
+}
+
+public final class HMACSHA256 {
+
+    public static let Lenght = Int(crypto_auth_hmacsha256_BYTES)
+
+    private var state: crypto_auth_hmacsha256_state
+
+    public var final: Bytes {
+        var out = Bytes(lenght: HMACSHA256.Lenght)
+        crypto_auth_hmacsha256_final(&state, &out.rawValue)
+        return out
+    }
+
+    public init(key: Bytes) throws {
+        guard key.lenght == crypto_auth_hmacsha256_KEYBYTES else { throw CryptoError.invalidKey }
+        state = crypto_auth_hmacsha256_state()
+        crypto_auth_hmacsha256_init(&state, key.rawValue, lenght(key))
+    }
+
+    public func update(_ bytes: Bytes) {
+        crypto_auth_hmacsha256_update(&state, bytes.rawValue, lenght(bytes));
+    }
+
+    public static func authenticate(_ bytes: Bytes, key: Bytes) throws -> Bytes {
+        let hmac = try HMACSHA256(key: key)
+        hmac.update(bytes)
+        return hmac.final
+    }
+
+}
+
+

+ 25 - 0
Sources/Crypto/KeyDerivation.swift

@@ -0,0 +1,25 @@
+// KeyDerivation.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+public protocol KeyDerivation {
+
+    func derive(key: Bytes) throws -> Bytes
+}

+ 56 - 0
Sources/Crypto/Salsa20.swift

@@ -0,0 +1,56 @@
+// Salsa20.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Sodium
+
+public final class Salsa20 {
+
+    public let key: Bytes
+
+    public let nonce: Bytes
+
+    public init(key: Bytes, iv nonce: Bytes) throws {
+
+        guard key.lenght == crypto_stream_salsa20_KEYBYTES else {
+            throw CryptoError.keyLenght(expecting: "Equal \(crypto_stream_salsa20_KEYBYTES)", got: key.lenght)
+        }
+
+        guard nonce.lenght == crypto_stream_salsa20_NONCEBYTES else {
+            throw CryptoError.ivLenght(expecting: "Equal \(crypto_stream_salsa20_NONCEBYTES)", got: nonce.lenght)
+        }
+
+        self.key = key
+        self.nonce = nonce
+    }
+}
+
+extension Salsa20: Cipher {
+
+    public func encrypt(data: Bytes) throws -> Bytes {
+        var out = Bytes(lenght: lenght(data))
+        crypto_stream_salsa20_xor(&out.rawValue, data.rawValue, lenght(data), nonce.rawValue, key.rawValue);
+        return out
+    }
+
+    public func decrypt(data: Bytes) throws -> Bytes {
+        return try encrypt(data: data)
+    }
+
+}

+ 59 - 0
Sources/Crypto/Twofish.swift

@@ -0,0 +1,59 @@
+// Twofish.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Twofish
+
+public final class Twofish {
+
+    private var context: twofish_context
+
+    public init(key: Bytes, iv: Bytes) throws {
+
+        guard key.lenght <= TWOFISH_KEYSIZE else {
+            throw CryptoError.keyLenght(expecting: "Less or equal to \(TWOFISH_KEYSIZE)", got: key.lenght)
+        }
+
+        guard iv.lenght == TWOFISH_IVSIZE else {
+            throw CryptoError.ivLenght(expecting: "Equal to \(TWOFISH_IVSIZE)", got: iv.lenght)
+        }
+
+        context = twofish_context()
+        twofish_setup(&context, key.rawValue, iv.rawValue, twofish_options_default)
+    }
+    
+}
+
+extension Twofish: Cipher {
+    
+    public func encrypt(data: Bytes) throws -> Bytes {
+        let output_length = twofish_get_output_length(&context, lenght(data))
+        var out = Bytes(lenght: Int(output_length))
+        twofish_encrypt(&context, data.rawValue, lenght(data), &out.rawValue, output_length)
+        return out
+    }
+
+    public func decrypt(data: Bytes) throws -> Bytes {
+        var out = Bytes(lenght: data.lenght)
+        var output_length = data.lenght
+        twofish_decrypt(&context, data.rawValue, output_length, &out.rawValue, &output_length)
+        return out.prefix(output_length)
+    }
+    
+}

+ 290 - 0
Sources/Gzip/Gzip.swift

@@ -0,0 +1,290 @@
+//
+//  DataGzip.swift
+//
+
+/*
+ The MIT License (MIT)
+
+ © 2014-2019 1024jp <wolfrosch.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+import Foundation
+import Binary
+
+#if os(Linux)
+    import zlibLinux
+#else
+    import zlib
+#endif
+
+/// Compression level whose rawValue is based on the zlib's constants.
+public struct CompressionLevel: RawRepresentable {
+
+    public static let noCompression = CompressionLevel(rawValue: Z_NO_COMPRESSION)
+
+    public static let bestSpeed = CompressionLevel(rawValue: Z_BEST_SPEED)
+
+    public static let bestCompression = CompressionLevel(rawValue: Z_BEST_COMPRESSION)
+
+    public static let defaultCompression = CompressionLevel(rawValue: Z_DEFAULT_COMPRESSION)
+
+    /// Compression level in the range of `0` (no compression) to `9` (maximum compression).
+    public let rawValue: Int32
+
+    public init(rawValue: Int32) {
+        self.rawValue = rawValue
+    }
+
+}
+
+
+/// Errors on gzipping/gunzipping based on the zlib error codes.
+public struct GzipError: Swift.Error {
+    // cf. http://www.zlib.net/manual.html
+
+    public enum Kind: Equatable {
+        /// The stream structure was inconsistent.
+        ///
+        /// - underlying zlib error: `Z_STREAM_ERROR` (-2)
+        case stream
+
+        /// The input data was corrupted
+        /// (input stream not conforming to the zlib format or incorrect check value).
+        ///
+        /// - underlying zlib error: `Z_DATA_ERROR` (-3)
+        case data
+
+        /// There was not enough memory.
+        ///
+        /// - underlying zlib error: `Z_MEM_ERROR` (-4)
+        case memory
+
+        /// No progress is possible or there was not enough room in the output buffer.
+        ///
+        /// - underlying zlib error: `Z_BUF_ERROR` (-5)
+        case buffer
+
+        /// The zlib library version is incompatible with the version assumed by the caller.
+        ///
+        /// - underlying zlib error: `Z_VERSION_ERROR` (-6)
+        case version
+
+        /// An unknown error occurred.
+        ///
+        /// - parameter code: return error by zlib
+        case unknown(code: Int)
+    }
+
+    /// Error kind.
+    public let kind: Kind
+
+    /// Returned message by zlib.
+    public let message: String
+
+    internal init(code: Int32, msg: UnsafePointer<CChar>?) {
+
+        self.message = {
+            guard let msg = msg, let message = String(validatingUTF8: msg) else {
+                return "Unknown gzip error"
+            }
+            return message
+        }()
+
+        self.kind = {
+            switch code {
+            case Z_STREAM_ERROR:
+                return .stream
+            case Z_DATA_ERROR:
+                return .data
+            case Z_MEM_ERROR:
+                return .memory
+            case Z_BUF_ERROR:
+                return .buffer
+            case Z_VERSION_ERROR:
+                return .version
+            default:
+                return .unknown(code: Int(code))
+            }
+        }()
+    }
+
+    public var localizedDescription: String { message }
+
+}
+
+extension Bytes {
+
+    /// Whether the receiver is compressed in gzip format.
+    public var isGzipped: Bool {
+        starts(with: [0x1f, 0x8b])  // check magic number
+    }
+
+    /// Create a new `Data` object by compressing the receiver using zlib.
+    /// Throws an error if compression failed.
+    ///
+    /// - Parameter level: Compression level.
+    /// - Returns: Gzip-compressed `Data` object.
+    /// - Throws: `GzipError`
+    public func gzipped(level: CompressionLevel = .defaultCompression) throws -> Bytes {
+        guard !isEmpty else { return Bytes() }
+
+        var stream = z_stream()
+        var status: Int32
+
+        status = deflateInit2_(&stream,
+                               level.rawValue,
+                               Z_DEFLATED, MAX_WBITS + 16,
+                               MAX_MEM_LEVEL,
+                               Z_DEFAULT_STRATEGY,
+                               ZLIB_VERSION,
+                               Int32(DataSize.stream))
+
+        guard status == Z_OK else {
+            // deflateInit2 returns:
+            // Z_VERSION_ERROR  The zlib library version is incompatible with the version assumed by the caller.
+            // Z_MEM_ERROR      There was not enough memory.
+            // Z_STREAM_ERROR   A parameter is invalid.
+
+            throw GzipError(code: status, msg: stream.msg)
+        }
+
+        var out = Bytes(lenght: DataSize.chunk)
+
+        repeat {
+
+            if Int(stream.total_out) >= out.count {
+                out += Bytes(lenght: DataSize.chunk)
+            }
+
+            let outputCount = out.count
+
+            try withUnsafeBytes { input in
+                guard let pointer = input.bindMemory(to: Bytef.self).baseAddress else {
+                    throw GzipError.init(code: 0, msg: nil)
+                }
+
+                stream.next_in = UnsafeMutablePointer<Bytef>(mutating: pointer).advanced(by: Int(stream.total_in))
+                stream.avail_in = uInt(count) - uInt(stream.total_in)
+
+                try out.withUnsafeMutableBytes { output in
+                    guard let pointer = output.bindMemory(to: Bytef.self).baseAddress else {
+                        throw GzipError.init(code: 0, msg: nil)
+                    }
+
+                    stream.next_out = pointer.advanced(by: Int(stream.total_out))
+                    stream.avail_out = uInt(outputCount) - uInt(stream.total_out)
+
+                    status = deflate(&stream, Z_FINISH)
+
+                    stream.next_out = nil
+                }
+
+                stream.next_in = nil
+            }
+
+        } while stream.avail_out == 0
+
+        guard deflateEnd(&stream) == Z_OK, status == Z_STREAM_END else {
+            throw GzipError(code: status, msg: stream.msg)
+        }
+
+        return out.prefix(Int(stream.total_out))
+    }
+
+
+    /// Create a new `Data` object by decompressing the receiver using zlib.
+    /// Throws an error if decompression failed.
+    ///
+    /// - Returns: Gzip-decompressed `Data` object.
+    /// - Throws: `GzipError`
+    public func gunzipped() throws -> Bytes {
+        guard !isEmpty else { return Bytes() }
+
+        var stream = z_stream()
+        var status: Int32
+
+        status = inflateInit2_(&stream, MAX_WBITS + 32, ZLIB_VERSION, Int32(DataSize.stream))
+
+        guard status == Z_OK else {
+            // inflateInit2 returns:
+            // Z_VERSION_ERROR   The zlib library version is incompatible with the version assumed by the caller.
+            // Z_MEM_ERROR       There was not enough memory.
+            // Z_STREAM_ERROR    A parameters are invalid.
+
+            throw GzipError(code: status, msg: stream.msg)
+        }
+
+        var out = Bytes(lenght: count * 2)
+
+        repeat {
+
+            if Int(stream.total_out) >= out.count {
+                out += Bytes(lenght: count * 2)
+            }
+
+            let outputCount = out.count
+
+            try withUnsafeBytes { input in
+                guard let pointer = input.bindMemory(to: Bytef.self).baseAddress else {
+                    throw GzipError.init(code: 0, msg: nil)
+                }
+
+                stream.next_in = UnsafeMutablePointer<Bytef>(mutating: pointer).advanced(by: Int(stream.total_in))
+                
+                stream.avail_in = uInt(count) - uInt(stream.total_in)
+
+                try out.withUnsafeMutableBytes { output in
+                    guard let pointer = output.bindMemory(to: Bytef.self).baseAddress else {
+                        throw GzipError.init(code: 0, msg: nil)
+                    }
+
+                    stream.next_out = pointer.advanced(by: Int(stream.total_out))
+                    stream.avail_out = uInt(outputCount) - uInt(stream.total_out)
+
+                    status = inflate(&stream, Z_SYNC_FLUSH)
+
+                    stream.next_out = nil
+                }
+
+                stream.next_in = nil
+            }
+
+        } while status == Z_OK
+
+        guard inflateEnd(&stream) == Z_OK, status == Z_STREAM_END else {
+            // inflate returns:
+            // Z_DATA_ERROR   The input data was corrupted (input stream not conforming to the zlib format or incorrect check value).
+            // Z_STREAM_ERROR The stream structure was inconsistent (for example if next_in or next_out was NULL).
+            // Z_MEM_ERROR    There was not enough memory.
+            // Z_BUF_ERROR    No progress is possible or there was not enough room in the output buffer when Z_FINISH is used.
+
+            throw GzipError(code: status, msg: stream.msg)
+        }
+
+        return out.prefix(Int(stream.total_out))
+    }
+
+}
+
+private struct DataSize {
+    static let chunk = 1 << 14
+    static let stream = MemoryLayout<z_stream>.size
+}

+ 21 - 0
Sources/Gzip/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2019 1024jp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 50 - 0
Sources/KDB/CompositeKey.swift

@@ -0,0 +1,50 @@
+// CompositeKey.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Binary
+import Crypto
+
+public protocol CompositeKey {
+
+    var password: String { get }
+
+    var key: Bytes { get }
+}
+
+extension CompositeKey {
+
+    func serialize() throws -> Bytes {
+        guard let password = Bytes(string: password, using: .isoLatin1) else {
+            throw KDBError.invalidPassword
+        }
+
+        if password.isEmpty, key.isEmpty {
+            throw KDBError.emptyCompositeKey
+        }
+
+        if key.isEmpty {
+            return SHA256.hash(password)
+        }
+
+        if password.isEmpty {
+            return key
+        }
+
+        return SHA256.hash( SHA256.hash(password) + key )
+    }
+}

+ 124 - 0
Sources/KDB/Database.swift

@@ -0,0 +1,124 @@
+// Database.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Crypto
+
+public let FileSignature: UInt32 = 0x9AA2D903
+public let FileFormat: UInt32 = 0xB54BFB65
+
+public class Database {
+
+    let header: Header
+
+    public private(set) var root: Group!
+
+    public required init(from input: Input, compositeKey: CompositeKey) throws {
+        header = try input.read()
+
+        let data = try input.read() as Bytes
+        let key = try header.masterKey(from: compositeKey)
+
+        let cipher: Cipher
+
+        if header.cipher.contains(.aes) {
+            cipher = try AESCipher(key: key, iv: header.initialVector)
+        } else if header.cipher.contains(.twofish) {
+            cipher = try Twofish(key: key, iv: header.initialVector)
+        } else {
+            throw KDBError.unsupportedCipher
+        }
+
+        let content = try cipher.decrypt(data: data)
+
+        guard SHA256.hash(content) == header.contentHash else {
+            throw KDBError.invalidKey
+        }
+
+        let stream = Input(bytes: content)
+        self.root = try tree(from: stream)
+    }
+
+    public convenience init(from file: URL, compositeKey: CompositeKey) throws {
+
+        let bytes = try Bytes(contentsOf: file)
+        let stream = Input(bytes: bytes)
+
+        guard
+            try stream.read() == FileSignature,
+            try stream.read() == FileFormat
+        else { throw KDBError.invalidFileFormat }
+
+        try self.init(from: stream, compositeKey: compositeKey)
+    }
+
+}
+
+extension Database: Writable {
+
+    public func write(to output: Output) throws {
+        try output.write(header)
+        fatalError()
+    }
+
+}
+
+extension Database {
+
+    private func tree(from input: Input) throws -> Group {
+
+        let groups: [Group] = try input.read(maxLenght: Int(header.groups))
+        let entries: [Entry] = try input.read(maxLenght: Int(header.entries))
+
+        let root = Group()
+
+        for (i, group) in groups.enumerated() {
+
+            guard let level1: UInt16 = group[.groupLevel] else { throw KDBError.corruptedDatabase }
+
+            if level1 == 0 {
+                root.childs.append(group)
+                continue
+            }
+
+            for (j, parent) in groups[0..<i].enumerated().reversed() {
+                guard let level2: UInt16 = parent[.groupLevel] else { throw KDBError.corruptedDatabase }
+
+                if level2 < level1 {
+                    guard (level1 - level2) == 1 else { throw KDBError.corruptedDatabase }
+                    parent.childs.append(group)
+                    break
+                }
+
+                guard j > 0 else { throw KDBError.corruptedDatabase }
+            }
+
+        }
+
+        for entry in entries {
+            guard let groupID: UInt32 = entry[.groupID] else { throw KDBError.corruptedDatabase }
+
+            let group = try groups.first(where: .groupID, { $0 == groupID }) ?? root
+            group.entries.append(entry)
+        }
+
+        return root
+    }
+
+}

+ 76 - 0
Sources/KDB/Date.swift

@@ -0,0 +1,76 @@
+// Date.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+extension Database {
+
+    public static let distantFuture: Date = {
+        DateComponents(calendar: Calendar(identifier: .iso8601),
+                       year: 2999,
+                       month: 12,
+                       day: 28,
+                       hour: 23,
+                       minute: 59,
+                       second: 59,
+                       nanosecond: 0).date!
+    }()
+
+    public static func date(from bytes: Bytes) -> Date? {
+        guard bytes.count > 4 else { return nil }
+
+        let year    = ( Int(bytes[0]) << 6) | (Int(bytes[1]) >> 2)
+        let month   = ((Int(bytes[1]) & 0x00000003) << 2) | (Int(bytes[2]) >> 6)
+        let day     = ( Int(bytes[2]) >> 1) & 0x0000001F
+        let hour    = ((Int(bytes[2]) & 0x00000001) << 4) | (Int(bytes[3]) >> 4)
+        let minute  = ((Int(bytes[3]) & 0x0000000F) << 2) | (Int(bytes[4]) >> 6)
+        let second  =   Int(bytes[4]) & 0x0000003F
+
+        return DateComponents(calendar: Calendar(identifier: .iso8601),
+                              year: year,
+                              month: month,
+                              day: day,
+                              hour: hour,
+                              minute: minute,
+                              second: second,
+                              nanosecond: 0).date
+
+    }
+
+    public static func bytes(from date: Date) -> Bytes {
+        let calendar = Calendar(identifier: .iso8601)
+        let components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
+
+        let year   = components.year!
+        let month  = UInt8(components.month!)
+        let day    = UInt8(components.day!)
+        let hour   = UInt8(components.hour!)
+        let minute = UInt8(components.minute!)
+        let second = UInt8(components.second!)
+
+        var bytes = Bytes(lenght: 5)
+        bytes[0] = UInt8(year >> 6) & 0x3F
+        bytes[1] = (UInt8(year & 0x3F) << 2) | ((month >> 2) & 0x03)
+        bytes[2] = ((month & 0x03) << 6) | ((day & 0x1F) << 1) | ((hour >> 4) & 0x01)
+        bytes[3] = (hour & 0x0F) << 4 | ((minute >> 2) & 0x0F)
+        bytes[4] = ((minute & 0x03) << 6) | (second & 0x3F)
+        return bytes
+
+    }
+}

+ 78 - 0
Sources/KDB/Entry.swift

@@ -0,0 +1,78 @@
+// Entry.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+let MetaEntryBinaryDescription   = "bin-stream"
+let MetaEntryTitle               = "Meta-Info"
+let MetaEntryUsername            = "SYSTEM"
+let MetaEntryURL                 = "$"
+
+let MetaEntryUIState                         = "Simple UI State"
+let MetaEntryDefaultUsername                 = "Default User Name"
+let MetaEntrySearchHistoryItem               = "Search History Item"
+let MetaEntryCustomKVP                       = "Custom KVP"
+let MetaEntryDatabaseColor                   = "Database Color"
+let MetaEntryKeePassXCustomIcon              = "KPX_CUSTOM_ICONS_2"
+let MetaEntryKeePassXCustomIcon2             = "KPX_CUSTOM_ICONS_4"
+let MetaEntryKeePassXGroupTreeState          = "KPX_GROUP_TREE_STATE"
+let MetaEntryKeePassKitGroupUUIDs            = "KeePassKit Group UUIDs"
+let MetaEntryKeePassKitDeletedObjects        = "KeePassKit Deleted Objects"
+let MetaEntryKeePassKitDatabaseName          = "KeePassKit Database Name"
+let MetaEntryKeePassKitDatabaseDescription   = "KeePassKit Database Description"
+let MetaEntryKeePassKitTrash                 = "KeePassKit Trash"
+let MetaEntryKeePassKitUserTemplates         = "KeePassKit User Templates"
+
+public final class Entry: Row, Streamable {
+
+    public static let End = Field.end
+
+    public enum Field: UInt16, Streamable {
+        case reserved           = 0x0000
+        case uuid               = 0x0001
+        case groupID            = 0x0002
+        case iconID             = 0x0003
+        case title              = 0x0004
+        case url                = 0x0005
+        case username           = 0x0006
+        case password           = 0x0007
+        case notes              = 0x0008
+        case creationTime       = 0x0009
+        case lastModifiedTime   = 0x000A
+        case lastAccessTime     = 0x000B
+        case expirationTime     = 0x000C
+        case binaryDesc         = 0x000D
+        case binaryData         = 0x000E
+        case end                = 0xFFFF
+    }
+
+    public var fields: [TLV<Field, UInt32>]
+
+    public required init() {
+        fields = []
+    }
+    
+}
+
+extension Entry {
+
+    var isMetaEntry: Bool {
+        return false
+    }
+}

+ 28 - 0
Sources/KDB/Error.swift

@@ -0,0 +1,28 @@
+// Error.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public enum KDBError: Error {
+    case invalidFileFormat
+    case corruptedDatabase
+    case unsupportedCipher
+    case emptyCompositeKey
+    case invalidPassword
+    case invalidKey
+}

+ 51 - 0
Sources/KDB/Group.swift

@@ -0,0 +1,51 @@
+// Group.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+public final class Group: Row, Streamable {
+
+    public static let End = Field.end
+
+    public enum Field: UInt16, Streamable {
+        case reserved           = 0x0000
+        case groupID            = 0x0001
+        case name               = 0x0002
+        case creationTime       = 0x0003
+        case lastModifiedTime   = 0x0004
+        case lastAccessTime     = 0x0005
+        case expirationTime     = 0x0006
+        case iconID             = 0x0007
+        case groupLevel         = 0x0008
+        case groupFlags         = 0x0009
+        case end                = 0xFFFF
+    }
+
+    public var fields: [TLV<Field, UInt32>]
+
+    public var childs: [Group]
+
+    public var entries: [Entry]
+
+    public required init() {
+        fields = []
+        childs = []
+        entries = []
+    }
+}

+ 83 - 0
Sources/KDB/Header.swift

@@ -0,0 +1,83 @@
+// Header.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Crypto
+
+struct Header {
+    let cipher: Flag
+    let version: UInt32
+    let masterSeed: Bytes
+    let initialVector: Bytes
+    let groups: UInt32
+    let entries: UInt32
+    let contentHash: Bytes
+    let transformSeed: Bytes
+    let transformRounds: UInt32
+}
+
+struct Flag: OptionSet, Streamable {
+    let rawValue: UInt32
+
+    static let sha2     = Flag(rawValue: 1<<0)
+    static let aes      = Flag(rawValue: 1<<1)
+    static let arc4     = Flag(rawValue: 1<<2)
+    static let twofish  = Flag(rawValue: 1<<3)
+}
+
+extension Header: Streamable {
+
+    init(from input: Input) throws {
+        cipher = try input.read()
+        version = try input.read()
+        masterSeed = try input.read(lenght: 16)
+        initialVector = try input.read(lenght: 16)
+        groups = try input.read()
+        entries = try input.read()
+        contentHash = try input.read(lenght: 32)
+        transformSeed = try input.read(lenght: 32)
+        transformRounds = try input.read()
+    }
+
+    func write(to output: Output) throws {
+        try output.write(cipher)
+        try output.write(version)
+        try output.write(masterSeed)
+        try output.write(initialVector)
+        try output.write(groups)
+        try output.write(entries)
+        try output.write(contentHash)
+        try output.write(transformSeed)
+        try output.write(transformRounds)
+    }
+
+}
+
+extension Header {
+
+    func masterKey(from compositeKey: CompositeKey) throws -> Bytes {
+        let key = try compositeKey.serialize()
+
+        // Key Derivation
+        let kdf = try AESKeyDerivation(seed: transformSeed, rounds: UInt64(transformRounds))
+        let derivedKey = try kdf.derive(key: key)
+
+        return SHA256.hash( masterSeed + derivedKey )
+    }
+}

+ 93 - 0
Sources/KDB/Row.swift

@@ -0,0 +1,93 @@
+// Row.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+public protocol Row {
+    associatedtype Field: Streamable, Equatable
+
+    init()
+
+    var fields: [TLV<Field, UInt32>] { get set }
+
+    static var End: Field { get }
+}
+
+extension Row {
+
+    public subscript (_ field: Field) -> Bytes? {
+        get { fields.first(where: { $0.type == field })?.value }
+        set {
+            fields.removeAll(where: { $0.type == field })
+            guard let value = newValue else { return }
+            let tlv = TLV<Field, UInt32>(type: field, value: value)
+            fields.insert(tlv, at: 0)
+        }
+    }
+
+    public subscript <T>(_ field: Field) -> T? where T: BytesRepresentable {
+        get {
+            guard let bytes = self[field] else { return nil }
+            return try? T(bytes)
+        }
+        set { self[field] = newValue?.bytes }
+    }
+}
+
+extension Readable where Self: Row {
+
+    public init(from input: Input) throws {
+        self.init()
+        while true {
+            let field: TLV<Field, UInt32> = try input.read()
+            guard field.type != Self.End else { break }
+            fields.append(field)
+        }
+    }
+
+}
+
+extension Writable where Self: Row {
+
+    public func write(to output: Output) throws {
+        try output.write(fields)
+        let end = TLV<Field, UInt32>(type: Self.End, value: [])
+        try output.write(end)
+    }
+    
+}
+
+extension Sequence where Element: Row {
+
+    public func first<T>(where field: Element.Field, _ predicate: (T) throws -> Bool) throws -> Element? where T: BytesRepresentable {
+        return try first(where: {
+            guard let bytes = $0[field] else { return false }
+            return try predicate(try T(bytes))
+        })
+    }
+
+    public func sorted<T>(field: Element.Field, by areInIncreasingOrder: (T, T) throws -> Bool) throws -> [Self.Element] where T: BytesRepresentable {
+        return try sorted(by: {
+            guard let rhs = $0[field], let lhs = $1[field] else { return false }
+            return try areInIncreasingOrder(try T(rhs), try T(lhs))
+        })
+    }
+
+    
+}

+ 41 - 0
Sources/KDBX/Cipher.swift

@@ -0,0 +1,41 @@
+// Cipher.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Crypto
+
+extension AESCipher {
+
+    static let UUID = Foundation.UUID(uuid: (0x31, 0xC1, 0xF2, 0xE6, 0xBF, 0x71, 0x43, 0x50,
+                                             0xBE, 0x58, 0x05, 0x21, 0x6A, 0xFC, 0x5A, 0xFF))
+
+}
+
+extension ChaCha20 {
+
+    static let UUID = Foundation.UUID(uuid: (0xD6, 0x03, 0x8A, 0x2B, 0x8B, 0x6F, 0x4C, 0xB5,
+                                             0xA5, 0x24, 0x33, 0x9A, 0x31, 0xDB, 0xB5, 0x9A))
+
+}
+
+extension Twofish {
+
+    static let UUID = Foundation.UUID(uuid: (0xAD, 0x68, 0xF2, 0x9F, 0x57, 0x6F, 0x4B, 0xB9,
+                                             0xA3, 0x6A, 0xD4, 0x7A, 0xF9, 0x65, 0x34, 0x6C))
+
+}

+ 53 - 0
Sources/KDBX/CompositeKey.swift

@@ -0,0 +1,53 @@
+// CompositeKey.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Binary
+import Crypto
+
+public protocol CompositeKey {
+
+    var password: String { get }
+
+    var key: Bytes { get }
+}
+
+extension CompositeKey {
+
+    func serialize() throws -> Bytes {
+        guard let password = Bytes(string: password, using: .utf8) else {
+            throw KDBXError.invalidPassword
+        }
+
+        if password.isEmpty, key.isEmpty {
+            throw KDBXError.emptyCompositeKey
+        }
+
+        let hash = SHA256()
+
+        if !password.isEmpty {
+            hash.update( SHA256.hash(password) )
+        }
+
+        if !key.isEmpty {
+            hash.update(key)
+        }
+
+        return hash.final
+    }
+
+}

+ 25 - 0
Sources/KDBX/Database.swift

@@ -0,0 +1,25 @@
+// Database.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import XML
+
+public protocol Database {
+
+    var document: Document { get }
+}

+ 108 - 0
Sources/KDBX/Database3.swift

@@ -0,0 +1,108 @@
+// Database3.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Crypto
+import Gzip
+import XML
+
+class Database3: Database {
+
+    typealias Header = [TLV<OuterHeader, UInt16>]
+
+    let header: Header
+
+    let document: Document
+
+    required init(from input: Input, compositeKey: CompositeKey) throws {
+        header = try input.read()
+
+        guard let startBytes = header[.streamStartBytes] else { throw KDBXError.corruptedDatabase }
+
+        let data = try input.read() as Bytes
+
+        var key = try header.masterKey(from: compositeKey)
+        key = SHA256.hash( key )
+
+        let cipher = try header.cipher(key: key)
+
+        let hash = try cipher.decrypt(data: data)
+        let stream = Input(bytes: hash)
+
+        guard try stream.read(lenght: SHA256.Lenght) == startBytes else { throw KDBXError.invalidCompositeKey }
+
+        var block: UInt32 = 0
+        var content = Bytes()
+
+        while true {
+            guard try stream.read() == block else { throw KDBXError.corruptedDatabase }
+            block += 1
+
+            let hash = try stream.read(lenght: SHA256.Lenght)
+            let size: UInt32 = try stream.read()
+            guard size > 0 else { break }
+
+            let data = try stream.read(lenght: Int(size))
+            guard SHA256.hash( data ) == hash else { throw KDBXError.corruptedDatabase }
+            content += data
+        }
+
+        if header[.compressionFlags] == Compression.gzip {
+            content = try content.gunzipped()
+        }
+
+        var options = XML.Options()
+        options.parserSettings.shouldTrimWhitespace = false
+
+        document = try XML.Document(xml: content.data, options: options)
+    }
+
+}
+
+extension Database3: Writable {
+
+    func write(to output: Output) throws {
+        try output.write(header)
+        fatalError()
+    }
+}
+
+extension Database3.Header: Readable {
+    
+    public init(from input: Input) throws {
+        var header = Database3.Header()
+
+        while true {
+            let field: TLV<OuterHeader, UInt16> = try input.read()
+            header.append(field)
+            if field.type == .end { break }
+        }
+
+        self = header
+    }
+    
+}
+
+extension Database3.Header: Header {
+
+    subscript(_ type: OuterHeader) -> Bytes? {
+        return first(where: { $0.type == type })?.value
+    }
+
+}

+ 93 - 0
Sources/KDBX/Database4.swift

@@ -0,0 +1,93 @@
+// Database4.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Crypto
+import XML
+
+class Database4: Database {
+
+    struct Header {
+        let fields: [TLV<OuterHeader, UInt32>]
+        let data: Bytes
+    }
+
+    let header: Header
+
+    let document: Document
+
+    required init(from input: Input, compositeKey: CompositeKey) throws {
+        header = try input.read()
+
+        var key = try header.masterKey(from: compositeKey)
+        let hmacKey = SHA512.hash( UInt64.max.bytes + SHA512.hash( key + 1 ) )
+        key = SHA256.hash( key )
+
+        let data = try input.read() as Bytes
+        let stream = Input(bytes: data)
+
+        guard
+            try stream.read(lenght: SHA256.Lenght) == SHA256.hash( header.data ),
+            try stream.read(lenght: SHA256.Lenght) == HMACSHA256.authenticate(header.data, key: hmacKey)
+        else { throw KDBXError.corruptedDatabase }
+
+        let cipher = try header.cipher(key: key)
+        let hash = try cipher.decrypt(data: data)
+
+        fatalError()
+    }
+
+}
+
+extension Database4: Writable {
+
+    func write(to output: Output) throws {
+        try output.write(header)
+        fatalError()
+    }
+
+}
+
+extension Database4.Header: Streamable {
+
+    init(from input: Input) throws {
+        var fields = [TLV<OuterHeader, UInt32>]()
+
+        while true {
+            let field: TLV<OuterHeader, UInt32> = try input.read()
+            fields.append(field)
+            if field.type == .end { break }
+        }
+
+        self.fields = fields
+        self.data = input.bytes.prefix(input.offset)
+    }
+
+    func write(to output: Output) throws {
+        try output.write(fields)
+    }
+
+}
+
+extension Database4.Header: Header {
+
+    subscript(_ field: OuterHeader) -> Bytes? {
+        return fields.first(where: { $0.type == field })?.value
+    }
+}

+ 30 - 0
Sources/KDBX/Error.swift

@@ -0,0 +1,30 @@
+// Error.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+
+public enum KDBXError: Error {
+    case invalidFileFormat
+    case invalidValue
+    case corruptedDatabase
+    case emptyCompositeKey
+    case unsupportedKeyDerivation
+    case unsupportedCipher
+    case invalidPassword
+    case invalidCompositeKey
+}

+ 88 - 0
Sources/KDBX/File.swift

@@ -0,0 +1,88 @@
+// File.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+public let FileSignature: UInt32 = 0x9AA2D903
+
+public let BetaFileFormat: UInt32 = 0xB54BFB66
+
+public let FileFormat: UInt32 = 0xB54BFB67
+
+public struct Version {
+    let major: UInt16
+    let minor: UInt16
+}
+
+public class File {
+
+    public let version: Version
+
+    public let database: Database & Writable
+
+    public required init(from input: Input, compositeKey: CompositeKey) throws {
+        version = try input.read()
+
+        if version.major > 3 {
+            database = try Database4(from: input, compositeKey: compositeKey)
+        } else {
+            database = try Database3(from: input, compositeKey: compositeKey)
+        }
+    }
+
+    public convenience init(from file: URL, compositeKey: CompositeKey) throws {
+
+        let bytes = try Bytes(contentsOf: file)
+        let stream = Input(bytes: bytes)
+
+        guard try stream.read() == FileSignature else { throw KDBXError.invalidFileFormat }
+
+        let format = try stream.read() as UInt32
+        guard
+            format == BetaFileFormat ||
+            format == FileFormat
+        else { throw KDBXError.invalidFileFormat }
+
+        try self.init(from: stream, compositeKey: compositeKey)
+    }
+}
+
+extension File: Writable {
+
+    public func write(to output: Output) throws {
+        try output.write(version)
+        // `try output.write(version)` error: Protocol type 'Writable & Database' cannot conform to 'Writable' because only concrete types can conform to protocols
+        try database.write(to: output)
+    }
+
+}
+
+extension Version: Streamable {
+
+    public init(from input: Input) throws {
+        minor = try input.read()
+        major = try input.read()
+    }
+
+    public func write(to output: Output) throws {
+        try output.write(minor)
+        try output.write(major)
+    }
+
+}

+ 119 - 0
Sources/KDBX/Header.swift

@@ -0,0 +1,119 @@
+// Header.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+import Crypto
+
+protocol Header {
+    subscript(_ type: OuterHeader) -> Bytes? { get }
+}
+
+enum OuterHeader: UInt8, Streamable {
+    case end                 = 0
+    case comment             = 1
+    case cipherID            = 2
+    case compressionFlags    = 3
+    case masterSeed          = 4
+    case transformSeed       = 5
+    case transformRounds     = 6
+    case initialVector       = 7
+    case protectedStreamKey  = 8
+    case streamStartBytes    = 9
+    case innerRandomStreamID = 10
+    case kdfParameters       = 11
+    case publicCustomData    = 12
+}
+
+enum InnerHeader: UInt8, Streamable {
+    case end                  = 0
+    case innerRandomStreamID  = 1
+    case innerRandomStreamKey = 2
+    case binary               = 3
+}
+
+enum Compression: UInt32, BytesRepresentable {
+    case none  = 0
+    case gzip  = 1
+    case count = 2
+}
+
+enum RandomStream: UInt32, BytesRepresentable {
+    case none       = 0
+    case arc4       = 1
+    case salsa20    = 2
+    case chacha20   = 3
+    case count      = 4
+}
+
+extension Header {
+
+    subscript<T>(_ type: OuterHeader) -> T? where T: BytesRepresentable {
+        guard let bytes = self[type] else { return nil }
+        return try? T(bytes)
+    }
+
+    func cipher(key: Bytes) throws -> Cipher {
+        guard
+            let uuid: UUID = self[.cipherID],
+            let iv = self[.initialVector]
+        else { throw KDBXError.corruptedDatabase }
+
+        switch uuid {
+        case AESCipher.UUID:
+            return try AESCipher(key: key, iv: iv)
+        case Twofish.UUID:
+            return try Twofish(key: key, iv: iv)
+        case ChaCha20.UUID:
+            return try ChaCha20(key: key, iv: iv)
+        default:
+            throw KDBXError.unsupportedCipher
+        }
+    }
+
+    func masterKey(from compositeKey: CompositeKey) throws -> Bytes {
+        guard let masterSeed = self[.masterSeed] else { throw KDBXError.corruptedDatabase }
+        let key = try compositeKey.serialize()
+
+        // Key Derivation
+        let derivedKey = try kdf().derive(key: key)
+
+        return masterSeed + derivedKey
+    }
+
+    func kdf() throws -> KeyDerivation {
+        
+        if let seed: Bytes = self[.transformSeed], let rounds: UInt64 = self[.transformRounds] {
+            return try AESKeyDerivation(seed: seed, rounds: rounds)
+        }
+
+        guard
+             let parameters: KeyDerivationParameters = self[.kdfParameters],
+             let uuid: UUID  = try parameters["$UUID"]?.unwrap()
+         else { throw KDBXError.corruptedDatabase }
+
+        switch uuid {
+        case Argon2.UUID:
+            return try Argon2(parameters: parameters)
+        case AESKeyDerivation.UUID:
+            return try AESKeyDerivation(parameters: parameters)
+        default:
+            throw KDBXError.unsupportedKeyDerivation
+        }
+    }
+}

+ 70 - 0
Sources/KDBX/KeyDerivation.swift

@@ -0,0 +1,70 @@
+// KeyDerivation.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Crypto
+
+
+typealias KeyDerivationParameters = [String: Variant]
+
+extension AESKeyDerivation {
+
+    static let UUID = Foundation.UUID(uuid:(0xC9, 0xD9, 0xF3, 0x9A, 0x62, 0x8A, 0x44, 0x60,
+                                            0xBF, 0x74, 0x0D, 0x08, 0xC1, 0x8A, 0x4F, 0xEA))
+
+    static let TransformSeedKey     = "S"
+    static let TransformRoundsKey   = "R"
+
+    convenience init(parameters: [String: Variant]) throws {
+        guard
+            let seed = parameters[AESKeyDerivation.TransformSeedKey],
+            let rounds = parameters[AESKeyDerivation.TransformRoundsKey]
+        else { throw KDBXError.corruptedDatabase }
+
+        try self.init(seed: try seed.unwrap(),
+                      rounds: try rounds.unwrap())
+    }
+}
+
+extension Argon2 {
+
+    static let UUID = Foundation.UUID(uuid:(0xEF, 0x63, 0x6D, 0xDF, 0x8C, 0x29, 0x44, 0x4B,
+                                            0x91, 0xF7, 0xA9, 0xA4, 0x03, 0xE3, 0x0A, 0x0C))
+
+    static let SaltKey          = "S"
+    static let ParallelismKey   = "P"
+    static let MemoryKey        = "M"
+    static let IterationsKey    = "I"
+    static let VersionKey       = "V"
+    
+    convenience init(parameters: [String: Variant]) throws {
+        guard
+            let salt = parameters[Argon2.SaltKey],
+            let parallelism = parameters[Argon2.ParallelismKey],
+            let memory = parameters[Argon2.MemoryKey],
+            let iterations = parameters[Argon2.IterationsKey],
+            let version = parameters[Argon2.VersionKey]
+        else { throw KDBXError.corruptedDatabase }
+
+        self.init(salt:         try salt.unwrap(),
+                  parallelism:  try parallelism.unwrap(),
+                  memory:       UInt32(try memory.unwrap() as UInt64) / 1024,
+                  iterations:   UInt32(try iterations.unwrap() as UInt64),
+                  version:      try version.unwrap())
+    }
+}

+ 283 - 0
Sources/KDBX/Variant.swift

@@ -0,0 +1,283 @@
+// Variant.swift
+// This file is part of KeePassKit.
+//
+// Copyright © 2019 Maxime Epain. All rights reserved.
+//
+// KeePassKit 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 3 of the License, or
+// (at your option) any later version.
+//
+// KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
+
+import Foundation
+import Binary
+
+public enum Variant {
+
+    struct Version {
+        let major: UInt8
+        let minor: UInt8
+    }
+
+    case End
+    case Bool(Bool)
+    case UInt32(UInt32)
+    case UInt64(UInt64)
+    case Int32(Int32)
+    case Int64(Int64)
+    case String(String)
+    case Bytes(Bytes)
+
+    enum ID: UInt8, Streamable {
+        case End     = 0x00
+        case Bool    = 0x08
+        case UInt32  = 0x04
+        case UInt64  = 0x05
+        case Int32   = 0x0C
+        case Int64   = 0x0D
+        case String  = 0x18
+        case Bytes   = 0x42
+    }
+
+    var id: ID {
+        switch self {
+        case .End:
+            return .End
+        case .Bool:
+            return .Bool
+        case .UInt32:
+            return .UInt32
+        case .UInt64:
+            return .UInt64
+        case .Int32:
+            return .Int32
+        case .Int64:
+            return .Int64
+        case .String:
+            return .String
+        case .Bytes:
+            return .Bytes
+        }
+    }
+
+    init() {
+        self = .End
+    }
+
+    init(_ value: Bool) {
+        self = .Bool(value)
+    }
+
+    init(_ value: UInt32) {
+        self = .UInt32(value)
+    }
+
+    init(_ value: UInt64) {
+        self = .UInt64(value)
+    }
+
+    init(_ value: Int32) {
+        self = .Int32(value)
+    }
+
+    init(_ value: Int64) {
+        self = .Int64(value)
+    }
+
+    init(_ value: String) {
+        self = .String(value)
+    }
+
+    init(_ value: Bytes) {
+        self = .Bytes(value)
+    }
+
+    func unwrap() throws -> Bool {
+        guard case let .Bool(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap() throws -> UInt32 {
+        guard case let .UInt32(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap() throws -> UInt64 {
+        guard case let .UInt64(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap() throws -> Int32 {
+        guard case let .Int32(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap() throws -> Int64 {
+        guard case let .Int64(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap() throws -> String {
+        guard case let .String(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap() throws -> Bytes {
+        guard case let .Bytes(value) = self else { throw KDBXError.invalidValue }
+        return value
+    }
+
+    func unwrap<T>() throws -> T where T: BytesRepresentable {
+        guard case let .Bytes(bytes) = self else { throw KDBXError.invalidValue }
+        return try T(bytes)
+    }
+
+}
+
+extension Variant: Writable {
+
+    init(id: ID, from input: Input) throws {
+        let lenght: UInt32 = try input.read()
+
+        switch id {
+        case .Bool:
+            guard lenght == MemoryLayout<Bool>.size else { throw KDBXError.invalidValue }
+            self = .Bool(try input.read())
+
+        case .UInt32:
+            guard lenght == MemoryLayout<UInt32>.size else { throw KDBXError.invalidValue }
+            self = .UInt32(try input.read())
+
+        case .UInt64:
+            guard lenght == MemoryLayout<UInt64>.size else { throw KDBXError.invalidValue }
+            self = .UInt64(try input.read())
+
+        case .Int32:
+            guard lenght == MemoryLayout<Int32>.size else { throw KDBXError.invalidValue }
+            self = .Int32(try input.read())
+
+        case .Int64:
+            guard lenght == MemoryLayout<Int64>.size else { throw KDBXError.invalidValue }
+            self = .Int64(try input.read())
+
+        case .String:
+            self = .String(try input.read(lenght: Int(lenght)))
+
+        case .Bytes:
+            self = .Bytes(try input.read(lenght: Int(lenght)))
+
+        default:
+            throw KDBXError.invalidValue
+        }
+    }
+
+    public func write(to output: Output) throws {
+        switch self {
+
+        case .End:
+            try output.write(id)
+
+        case .Bool(let value):
+            try output.write(MemoryLayout<Bool>.size)
+            try output.write(value)
+
+        case .UInt32(let value):
+            try output.write(MemoryLayout<UInt32>.size)
+            try output.write(value)
+
+        case .UInt64(let value):
+            try output.write(MemoryLayout<UInt64>.size)
+            try output.write(value)
+
+        case .Int32(let value):
+            try output.write(MemoryLayout<Int32>.size)
+            try output.write(value)
+
+        case .Int64(let value):
+            try output.write(MemoryLayout<Int64>.size)
+            try output.write(value)
+
+        case .String(let value):
+            try output.write(Swift.UInt32(value.count))
+            try output.write(value)
+
+        case .Bytes(let value):
+            try output.write(Swift.UInt32(value.lenght))
+            try output.write(value)
+        }
+    }
+
+}
+
+extension Variant.Version: Streamable {
+
+    init(from input: Input) throws {
+        minor = try input.read()
+        major = try input.read()
+    }
+
+    func write(to output: Output) throws {
+        try output.write(minor)
+        try output.write(major)
+    }
+
+}
+
+extension Dictionary: Streamable where Key == String, Value == Variant {
+
+    public init(from input: Input) throws {
+        self.init()
+
+        let version: Variant.Version = try input.read()
+        guard version.major > 0 else { throw KDBXError.invalidValue }
+
+        while true {
+            let id: Variant.ID = try input.read()
+
+            if id == .End { break }
+
+            let lenght: UInt32 = try input.read()
+            let key: String = try input.read(lenght: Int(lenght))
+            let value = try Variant(id: id, from: input)
+
+            self[key] = value
+        }
+    }
+
+    public func write(to output: Output) throws {
+        let version = Variant.Version(major: 1, minor: 0)
+        try output.write(version)
+        
+        try forEach {
+            try output.write($0.value.id)
+            try output.write(UInt32($0.key.count))
+            try output.write($0.key)
+            try output.write($0.value)
+        }
+
+        try output.write(Variant.End)
+    }
+
+}
+
+extension Dictionary: BytesRepresentable where Key == String, Value == Variant {
+
+    public init(_ bytes: Bytes) throws {
+        let input = Input(bytes: bytes)
+        try self.init(from: input)
+    }
+
+    public var bytes: Bytes {
+        let output = Output()
+        try? output.write(self)
+        return output.bytes ?? []
+    }
+
+}

+ 3 - 0
Sources/KeePass/KeePass.swift

@@ -0,0 +1,3 @@
+struct KeePass {
+    var text = "Hello, World!"
+}

+ 18 - 0
Sources/Sodium/LICENSE

@@ -0,0 +1,18 @@
+/*
+ * ISC License
+ *
+ * Copyright (c) 2013-2019
+ * Frank Denis <j at pureftpd dot org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */

+ 1079 - 0
Sources/Sodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c

@@ -0,0 +1,1079 @@
+
+/*
+ * AES256-GCM, based on the "Intel Carry-Less Multiplication Instruction and its Usage for Computing
+ * the GCM Mode" paper and reference code, using the aggregated reduction method.
+ * Originally adapted by Romain Dolbeau.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_aes256gcm.h"
+#include "export.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "utils.h"
+
+#if defined(HAVE_TMMINTRIN_H) && defined(HAVE_WMMINTRIN_H)
+
+# ifdef __GNUC__
+#  pragma GCC target("ssse3")
+#  pragma GCC target("aes")
+#  pragma GCC target("pclmul")
+# endif
+
+#include <tmmintrin.h>
+#include <wmmintrin.h>
+
+#ifndef ENOSYS
+# define ENOSYS ENXIO
+#endif
+
+#if defined(__INTEL_COMPILER) || defined(_bswap64)
+#elif defined(_MSC_VER)
+# define _bswap64(a) _byteswap_uint64(a)
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+# define _bswap64(a) __builtin_bswap64(a)
+#else
+static inline uint64_t
+_bswap64(const uint64_t x)
+{
+    return
+        ((x << 56) & 0xFF00000000000000UL) | ((x << 40) & 0x00FF000000000000UL) |
+        ((x << 24) & 0x0000FF0000000000UL) | ((x <<  8) & 0x000000FF00000000UL) |
+        ((x >>  8) & 0x00000000FF000000UL) | ((x >> 24) & 0x0000000000FF0000UL) |
+        ((x >> 40) & 0x000000000000FF00UL) | ((x >> 56) & 0x00000000000000FFUL);
+}
+#endif
+
+typedef struct aes256gcm_state {
+    __m128i       rkeys[16];
+    unsigned char H[16];
+} aes256gcm_state;
+
+static inline void
+aesni_key256_expand(const unsigned char *key, __m128i * const rkeys)
+{
+    __m128i  X0, X1, X2, X3;
+    int      i = 0;
+
+    X0 = _mm_loadu_si128((const __m128i *) &key[0]);
+    rkeys[i++] = X0;
+
+    X2 = _mm_loadu_si128((const __m128i *) &key[16]);
+    rkeys[i++] = X2;
+
+#define EXPAND_KEY_1(S) do { \
+    X1 = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(X2, (S)), 0xff); \
+    X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X0), 0x10)); \
+    X0 = _mm_xor_si128(X0, X3); \
+    X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X0), 0x8c)); \
+    X0 = _mm_xor_si128(_mm_xor_si128(X0, X3), X1); \
+    rkeys[i++] = X0; \
+} while (0)
+
+#define EXPAND_KEY_2(S) do { \
+    X1 = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(X0, (S)), 0xaa); \
+    X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X2), 0x10)); \
+    X2 = _mm_xor_si128(X2, X3); \
+    X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X2), 0x8c)); \
+    X2 = _mm_xor_si128(_mm_xor_si128(X2, X3), X1); \
+    rkeys[i++] = X2; \
+} while (0)
+
+    X3 = _mm_setzero_si128();
+    EXPAND_KEY_1(0x01); EXPAND_KEY_2(0x01);
+    EXPAND_KEY_1(0x02); EXPAND_KEY_2(0x02);
+    EXPAND_KEY_1(0x04); EXPAND_KEY_2(0x04);
+    EXPAND_KEY_1(0x08); EXPAND_KEY_2(0x08);
+    EXPAND_KEY_1(0x10); EXPAND_KEY_2(0x10);
+    EXPAND_KEY_1(0x20); EXPAND_KEY_2(0x20);
+    EXPAND_KEY_1(0x40);
+}
+
+/** single, by-the-book AES encryption with AES-NI */
+static inline void
+aesni_encrypt1(unsigned char *out, __m128i nv, const __m128i *rkeys)
+{
+    __m128i temp = _mm_xor_si128(nv, rkeys[0]);
+
+    temp = _mm_aesenc_si128(temp, rkeys[1]);
+    temp = _mm_aesenc_si128(temp, rkeys[2]);
+    temp = _mm_aesenc_si128(temp, rkeys[3]);
+    temp = _mm_aesenc_si128(temp, rkeys[4]);
+    temp = _mm_aesenc_si128(temp, rkeys[5]);
+    temp = _mm_aesenc_si128(temp, rkeys[6]);
+    temp = _mm_aesenc_si128(temp, rkeys[7]);
+    temp = _mm_aesenc_si128(temp, rkeys[8]);
+    temp = _mm_aesenc_si128(temp, rkeys[9]);
+    temp = _mm_aesenc_si128(temp, rkeys[10]);
+    temp = _mm_aesenc_si128(temp, rkeys[11]);
+    temp = _mm_aesenc_si128(temp, rkeys[12]);
+    temp = _mm_aesenc_si128(temp, rkeys[13]);
+
+    temp = _mm_aesenclast_si128(temp, rkeys[14]);
+    _mm_storeu_si128((__m128i *) out, temp);
+}
+
+/** multiple-blocks-at-once AES encryption with AES-NI ;
+    on Haswell, aesenc has a latency of 7 and a throughput of 1
+    so the sequence of aesenc should be bubble-free if you
+    have at least 8 blocks. Let's build an arbitratry-sized
+    function */
+/* Step 1 : loading the nonce */
+/* load & increment the n vector (non-vectorized, unused for now) */
+#define NVDECLx(a)                                                             \
+    __m128i nv##a
+
+#define NVx(a)                                                                 \
+    nv##a = _mm_shuffle_epi8(_mm_load_si128((const __m128i *) n), pt);         \
+    n[3]++
+
+/* Step 2 : define value in round one (xor with subkey #0, aka key) */
+#define TEMPDECLx(a) \
+    __m128i temp##a
+
+#define TEMPx(a) \
+    temp##a = _mm_xor_si128(nv##a, rkeys[0])
+
+/* Step 3: one round of AES */
+#define AESENCx(a) \
+    temp##a = _mm_aesenc_si128(temp##a, rkeys[roundctr])
+
+/* Step 4: last round of AES */
+#define AESENCLASTx(a) \
+    temp##a = _mm_aesenclast_si128(temp##a, rkeys[14])
+
+/* Step 5: store result */
+#define STOREx(a) \
+    _mm_storeu_si128((__m128i *) (out + (a * 16)), temp##a)
+
+/* all the MAKE* macros are for automatic explicit unrolling */
+#define MAKE4(X) \
+    X(0);        \
+    X(1);        \
+    X(2);        \
+    X(3)
+
+#define MAKE8(X) \
+    X(0);        \
+    X(1);        \
+    X(2);        \
+    X(3);        \
+    X(4);        \
+    X(5);        \
+    X(6);        \
+    X(7)
+
+#define COUNTER_INC2(N) (N)[3] += 2
+
+/* create a function of unrolling N ; the MAKEN is the unrolling
+   macro, defined above. The N in MAKEN must match N, obviously. */
+#define FUNC(N, MAKEN)                                                                                \
+    static inline void aesni_encrypt##N(unsigned char *out, uint32_t *n, const __m128i *rkeys)        \
+    {                                                                                                 \
+        const __m128i pt = _mm_set_epi8(12, 13, 14, 15, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);        \
+        int           roundctr;                                                                       \
+        MAKEN(NVDECLx);                                                                               \
+        MAKEN(TEMPDECLx);                                                                             \
+                                                                                                      \
+        MAKEN(NVx);                                                                                   \
+        MAKEN(TEMPx);                                                                                 \
+        for (roundctr = 1; roundctr < 14; roundctr++) {                                               \
+            MAKEN(AESENCx);                                                                           \
+        }                                                                                             \
+        MAKEN(AESENCLASTx);                                                                           \
+        MAKEN(STOREx);                                                                                \
+    }
+
+FUNC(8, MAKE8)
+
+/* all GF(2^128) fnctions are by the book, meaning this one:
+   <https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf>
+*/
+
+static inline void
+addmul(unsigned char *c, const unsigned char *a, unsigned int xlen, const unsigned char *b)
+{
+    const __m128i rev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+    __m128i       A, B, C;
+    __m128i       tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
+    __m128i       tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18;
+    __m128i       tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
+    __m128i       tmp28, tmp29, tmp30, tmp31, tmp32, tmp33, tmp34, tmp35, tmp36;
+
+    if (xlen >= 16) {
+        A = _mm_loadu_si128((const __m128i *) a);
+    } else {
+        CRYPTO_ALIGN(16) unsigned char padded[16];
+        unsigned int i;
+
+        memset(padded, 0, 16);
+        for (i = 0; i < xlen; i++) {
+            padded[i] = a[i];
+        }
+        A = _mm_load_si128((const __m128i *) padded);
+    }
+    A = _mm_shuffle_epi8(A, rev);
+    B = _mm_loadu_si128((const __m128i *) b);
+    C = _mm_loadu_si128((const __m128i *) c);
+    A = _mm_xor_si128(A, C);
+    tmp3 = _mm_clmulepi64_si128(A, B, 0x00);
+    tmp4 = _mm_clmulepi64_si128(A, B, 0x10);
+    tmp5 = _mm_clmulepi64_si128(A, B, 0x01);
+    tmp6 = _mm_clmulepi64_si128(A, B, 0x11);
+    tmp10 = _mm_xor_si128(tmp4, tmp5);
+    tmp13 = _mm_slli_si128(tmp10, 8);
+    tmp11 = _mm_srli_si128(tmp10, 8);
+    tmp15 = _mm_xor_si128(tmp3, tmp13);
+    tmp17 = _mm_xor_si128(tmp6, tmp11);
+    tmp7 = _mm_srli_epi32(tmp15, 31);
+    tmp8 = _mm_srli_epi32(tmp17, 31);
+    tmp16 = _mm_slli_epi32(tmp15, 1);
+    tmp18 = _mm_slli_epi32(tmp17, 1);
+    tmp9 = _mm_srli_si128(tmp7, 12);
+    tmp22 = _mm_slli_si128(tmp8, 4);
+    tmp25 = _mm_slli_si128(tmp7, 4);
+    tmp29 = _mm_or_si128(tmp16, tmp25);
+    tmp19 = _mm_or_si128(tmp18, tmp22);
+    tmp20 = _mm_or_si128(tmp19, tmp9);
+    tmp26 = _mm_slli_epi32(tmp29, 31);
+    tmp23 = _mm_slli_epi32(tmp29, 30);
+    tmp32 = _mm_slli_epi32(tmp29, 25);
+    tmp27 = _mm_xor_si128(tmp26, tmp23);
+    tmp28 = _mm_xor_si128(tmp27, tmp32);
+    tmp24 = _mm_srli_si128(tmp28, 4);
+    tmp33 = _mm_slli_si128(tmp28, 12);
+    tmp30 = _mm_xor_si128(tmp29, tmp33);
+    tmp2 = _mm_srli_epi32(tmp30, 1);
+    tmp12 = _mm_srli_epi32(tmp30, 2);
+    tmp14 = _mm_srli_epi32(tmp30, 7);
+    tmp34 = _mm_xor_si128(tmp2, tmp12);
+    tmp35 = _mm_xor_si128(tmp34, tmp14);
+    tmp36 = _mm_xor_si128(tmp35, tmp24);
+    tmp31 = _mm_xor_si128(tmp30, tmp36);
+    tmp21 = _mm_xor_si128(tmp20, tmp31);
+    _mm_storeu_si128((__m128i *) c, tmp21);
+}
+
+/* pure multiplication, for pre-computing powers of H */
+static inline __m128i
+mulv(__m128i A, __m128i B)
+{
+    __m128i tmp3 = _mm_clmulepi64_si128(A, B, 0x00);
+    __m128i tmp4 = _mm_clmulepi64_si128(A, B, 0x10);
+    __m128i tmp5 = _mm_clmulepi64_si128(A, B, 0x01);
+    __m128i tmp6 = _mm_clmulepi64_si128(A, B, 0x11);
+    __m128i tmp10 = _mm_xor_si128(tmp4, tmp5);
+    __m128i tmp13 = _mm_slli_si128(tmp10, 8);
+    __m128i tmp11 = _mm_srli_si128(tmp10, 8);
+    __m128i tmp15 = _mm_xor_si128(tmp3, tmp13);
+    __m128i tmp17 = _mm_xor_si128(tmp6, tmp11);
+    __m128i tmp7 = _mm_srli_epi32(tmp15, 31);
+    __m128i tmp8 = _mm_srli_epi32(tmp17, 31);
+    __m128i tmp16 = _mm_slli_epi32(tmp15, 1);
+    __m128i tmp18 = _mm_slli_epi32(tmp17, 1);
+    __m128i tmp9 = _mm_srli_si128(tmp7, 12);
+    __m128i tmp22 = _mm_slli_si128(tmp8, 4);
+    __m128i tmp25 = _mm_slli_si128(tmp7, 4);
+    __m128i tmp29 = _mm_or_si128(tmp16, tmp25);
+    __m128i tmp19 = _mm_or_si128(tmp18, tmp22);
+    __m128i tmp20 = _mm_or_si128(tmp19, tmp9);
+    __m128i tmp26 = _mm_slli_epi32(tmp29, 31);
+    __m128i tmp23 = _mm_slli_epi32(tmp29, 30);
+    __m128i tmp32 = _mm_slli_epi32(tmp29, 25);
+    __m128i tmp27 = _mm_xor_si128(tmp26, tmp23);
+    __m128i tmp28 = _mm_xor_si128(tmp27, tmp32);
+    __m128i tmp24 = _mm_srli_si128(tmp28, 4);
+    __m128i tmp33 = _mm_slli_si128(tmp28, 12);
+    __m128i tmp30 = _mm_xor_si128(tmp29, tmp33);
+    __m128i tmp2 = _mm_srli_epi32(tmp30, 1);
+    __m128i tmp12 = _mm_srli_epi32(tmp30, 2);
+    __m128i tmp14 = _mm_srli_epi32(tmp30, 7);
+    __m128i tmp34 = _mm_xor_si128(tmp2, tmp12);
+    __m128i tmp35 = _mm_xor_si128(tmp34, tmp14);
+    __m128i tmp36 = _mm_xor_si128(tmp35, tmp24);
+    __m128i tmp31 = _mm_xor_si128(tmp30, tmp36);
+    __m128i C = _mm_xor_si128(tmp20, tmp31);
+
+    return C;
+}
+
+/* 4 multiply-accumulate at once; again
+   <https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf>
+   for the Aggregated Reduction Method & sample code.
+   Algorithm by Krzysztof Jankowski, Pierre Laurent - Intel */
+
+#define RED_DECL(a) __m128i H##a##_X##a##_lo, H##a##_X##a##_hi, tmp##a, tmp##a##B
+#define RED_SHUFFLE(a) X##a = _mm_shuffle_epi8(X##a, rev)
+#define RED_MUL_LOW(a) H##a##_X##a##_lo = _mm_clmulepi64_si128(H##a, X##a, 0x00)
+#define RED_MUL_HIGH(a) H##a##_X##a##_hi = _mm_clmulepi64_si128(H##a, X##a, 0x11)
+#define RED_MUL_MID(a)                          \
+    tmp##a = _mm_shuffle_epi32(H##a, 0x4e);     \
+    tmp##a##B = _mm_shuffle_epi32(X##a, 0x4e);  \
+    tmp##a = _mm_xor_si128(tmp##a, H##a);       \
+    tmp##a##B = _mm_xor_si128(tmp##a##B, X##a); \
+    tmp##a = _mm_clmulepi64_si128(tmp##a, tmp##a##B, 0x00)
+
+#define MULREDUCE4(rev, H0_, H1_, H2_, H3_, X0_, X1_, X2_, X3_, accv) \
+do { \
+    MAKE4(RED_DECL); \
+    __m128i lo, hi; \
+    __m128i tmp8, tmp9; \
+    __m128i H0 = H0_; \
+    __m128i H1 = H1_; \
+    __m128i H2 = H2_; \
+    __m128i H3 = H3_; \
+    __m128i X0 = X0_; \
+    __m128i X1 = X1_; \
+    __m128i X2 = X2_; \
+    __m128i X3 = X3_; \
+\
+/* byte-revert the inputs & xor the first one into the accumulator */ \
+\
+    MAKE4(RED_SHUFFLE); \
+    X3 = _mm_xor_si128(X3, accv); \
+\
+/* 4 low H*X (x0*h0) */ \
+\
+    MAKE4(RED_MUL_LOW); \
+    lo = _mm_xor_si128(H0_X0_lo, H1_X1_lo); \
+    lo = _mm_xor_si128(lo, H2_X2_lo); \
+    lo = _mm_xor_si128(lo, H3_X3_lo); \
+\
+/* 4 high H*X (x1*h1) */ \
+\
+    MAKE4(RED_MUL_HIGH); \
+    hi = _mm_xor_si128(H0_X0_hi, H1_X1_hi); \
+    hi = _mm_xor_si128(hi, H2_X2_hi); \
+    hi = _mm_xor_si128(hi, H3_X3_hi); \
+\
+/* 4 middle H*X, using Karatsuba, i.e. \
+     x1*h0+x0*h1 =(x1+x0)*(h1+h0)-x1*h1-x0*h0 \
+     we already have all x1y1 & x0y0 (accumulated in hi & lo) \
+     (0 is low half and 1 is high half) \
+  */ \
+/* permute the high and low 64 bits in H1 & X1, \
+     so create (h0,h1) from (h1,h0) and (x0,x1) from (x1,x0), \
+     then compute (h0+h1,h1+h0) and (x0+x1,x1+x0), \
+     and finally multiply \
+  */ \
+    MAKE4(RED_MUL_MID); \
+\
+/* substracts x1*h1 and x0*h0 */ \
+    tmp0 = _mm_xor_si128(tmp0, lo); \
+    tmp0 = _mm_xor_si128(tmp0, hi); \
+    tmp0 = _mm_xor_si128(tmp1, tmp0); \
+    tmp0 = _mm_xor_si128(tmp2, tmp0); \
+    tmp0 = _mm_xor_si128(tmp3, tmp0);\
+\
+    /* reduction */ \
+    tmp0B = _mm_slli_si128(tmp0, 8); \
+    tmp0 = _mm_srli_si128(tmp0, 8); \
+    lo = _mm_xor_si128(tmp0B, lo); \
+    hi = _mm_xor_si128(tmp0, hi); \
+    tmp3 = lo; \
+    tmp2B = hi; \
+    tmp3B = _mm_srli_epi32(tmp3, 31); \
+    tmp8 = _mm_srli_epi32(tmp2B, 31); \
+    tmp3 = _mm_slli_epi32(tmp3, 1); \
+    tmp2B = _mm_slli_epi32(tmp2B, 1); \
+    tmp9 = _mm_srli_si128(tmp3B, 12); \
+    tmp8 = _mm_slli_si128(tmp8, 4); \
+    tmp3B = _mm_slli_si128(tmp3B, 4); \
+    tmp3 = _mm_or_si128(tmp3, tmp3B); \
+    tmp2B = _mm_or_si128(tmp2B, tmp8); \
+    tmp2B = _mm_or_si128(tmp2B, tmp9); \
+    tmp3B = _mm_slli_epi32(tmp3, 31); \
+    tmp8 = _mm_slli_epi32(tmp3, 30); \
+    tmp9 = _mm_slli_epi32(tmp3, 25); \
+    tmp3B = _mm_xor_si128(tmp3B, tmp8); \
+    tmp3B = _mm_xor_si128(tmp3B, tmp9); \
+    tmp8 = _mm_srli_si128(tmp3B, 4); \
+    tmp3B = _mm_slli_si128(tmp3B, 12); \
+    tmp3 = _mm_xor_si128(tmp3, tmp3B); \
+    tmp2 = _mm_srli_epi32(tmp3, 1); \
+    tmp0B = _mm_srli_epi32(tmp3, 2); \
+    tmp1B = _mm_srli_epi32(tmp3, 7); \
+    tmp2 = _mm_xor_si128(tmp2, tmp0B); \
+    tmp2 = _mm_xor_si128(tmp2, tmp1B); \
+    tmp2 = _mm_xor_si128(tmp2, tmp8); \
+    tmp3 = _mm_xor_si128(tmp3, tmp2); \
+    tmp2B = _mm_xor_si128(tmp2B, tmp3); \
+\
+    accv = tmp2B; \
+} while(0)
+
+#define XORx(a)                                                       \
+        temp##a = _mm_xor_si128(temp##a,                              \
+                                _mm_loadu_si128((const __m128i *) (in + a * 16)))
+
+#define LOADx(a)                                                      \
+    __m128i in##a = _mm_loadu_si128((const __m128i *) (in + a * 16))
+
+/* full encrypt & checksum 8 blocks at once */
+#define aesni_encrypt8full(out_, n_, rkeys, in_, accum, hv_, h2v_, h3v_, h4v_, rev) \
+do { \
+    unsigned char *out = out_; \
+    uint32_t *n = n_; \
+    const unsigned char *in = in_; \
+    const __m128i hv = hv_; \
+    const __m128i h2v = h2v_; \
+    const __m128i h3v = h3v_; \
+    const __m128i h4v = h4v_; \
+    const __m128i pt = _mm_set_epi8(12, 13, 14, 15, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); \
+    __m128i       accv_; \
+    int           roundctr; \
+    \
+    MAKE8(NVDECLx); \
+    MAKE8(TEMPDECLx); \
+    MAKE8(NVx); \
+    MAKE8(TEMPx); \
+    for (roundctr = 1; roundctr < 14; roundctr++) { \
+        MAKE8(AESENCx); \
+    } \
+    MAKE8(AESENCLASTx); \
+    MAKE8(XORx); \
+    MAKE8(STOREx); \
+    accv_ = _mm_load_si128((const __m128i *) accum); \
+    MULREDUCE4(rev, hv, h2v, h3v, h4v, temp3, temp2, temp1, temp0, accv_); \
+    MULREDUCE4(rev, hv, h2v, h3v, h4v, temp7, temp6, temp5, temp4, accv_); \
+    _mm_store_si128((__m128i *) accum, accv_); \
+} while(0)
+
+/* checksum 8 blocks at once */
+#define aesni_addmul8full(in_, accum, hv_, h2v_, h3v_, h4v_, rev) \
+do { \
+    const unsigned char *in = in_; \
+    const __m128i hv = hv_; \
+    const __m128i h2v = h2v_; \
+    const __m128i h3v = h3v_; \
+    const __m128i h4v = h4v_; \
+    __m128i accv_; \
+    \
+    MAKE8(LOADx); \
+    accv_ = _mm_load_si128((const __m128i *) accum); \
+    MULREDUCE4(rev, hv, h2v, h3v, h4v, in3, in2, in1, in0, accv_); \
+    MULREDUCE4(rev, hv, h2v, h3v, h4v, in7, in6, in5, in4, accv_); \
+    _mm_store_si128((__m128i *) accum, accv_); \
+} while(0)
+
+/* decrypt 8 blocks at once */
+#define aesni_decrypt8full(out_, n_, rkeys, in_) \
+do { \
+    unsigned char       *out = out_; \
+    uint32_t            *n = n_; \
+    const unsigned char *in = in_; \
+    const __m128i        pt = _mm_set_epi8(12, 13, 14, 15, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); \
+    int                  roundctr; \
+\
+    MAKE8(NVDECLx); \
+    MAKE8(TEMPDECLx); \
+    MAKE8(NVx); \
+    MAKE8(TEMPx); \
+    for (roundctr = 1; roundctr < 14; roundctr++) { \
+        MAKE8(AESENCx); \
+    } \
+    MAKE8(AESENCLASTx); \
+    MAKE8(XORx); \
+    MAKE8(STOREx); \
+} while(0)
+
+int
+crypto_aead_aes256gcm_beforenm(crypto_aead_aes256gcm_state *ctx_,
+                               const unsigned char *k)
+{
+    aes256gcm_state *ctx = (aes256gcm_state *) (void *) ctx_;
+    unsigned char   *H = ctx->H;
+    __m128i         *rkeys = ctx->rkeys;
+    __m128i          zero = _mm_setzero_si128();
+
+    COMPILER_ASSERT((sizeof *ctx_) >= (sizeof *ctx));
+    aesni_key256_expand(k, rkeys);
+    aesni_encrypt1(H, zero, rkeys);
+
+    return 0;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_detached_afternm(unsigned char *c,
+                                               unsigned char *mac, unsigned long long *maclen_p,
+                                               const unsigned char *m, unsigned long long mlen,
+                                               const unsigned char *ad, unsigned long long adlen,
+                                               const unsigned char *nsec,
+                                               const unsigned char *npub,
+                                               const crypto_aead_aes256gcm_state *ctx_)
+{
+    const __m128i          rev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+    const aes256gcm_state *ctx = (const aes256gcm_state *) (const void *) ctx_;
+    const __m128i         *rkeys = ctx->rkeys;
+    __m128i                Hv, H2v, H3v, H4v, accv;
+    unsigned long long     i, j;
+    unsigned long long     adlen_rnd64 = adlen & ~63ULL;
+    unsigned long long     mlen_rnd128 = mlen & ~127ULL;
+    CRYPTO_ALIGN(16) uint32_t      n2[4];
+    CRYPTO_ALIGN(16) unsigned char H[16];
+    CRYPTO_ALIGN(16) unsigned char T[16];
+    CRYPTO_ALIGN(16) unsigned char accum[16];
+    CRYPTO_ALIGN(16) unsigned char fb[16];
+
+    (void) nsec;
+    memcpy(H, ctx->H, sizeof H);
+    if (mlen > crypto_aead_aes256gcm_MESSAGEBYTES_MAX) {
+        sodium_misuse(); /* LCOV_EXCL_LINE */
+    }
+    memcpy(&n2[0], npub, 3 * 4);
+    n2[3] = 0x01000000;
+    aesni_encrypt1(T, _mm_load_si128((const __m128i *) n2), rkeys);
+    {
+        uint64_t x;
+        x = _bswap64((uint64_t) (8 * adlen));
+        memcpy(&fb[0], &x, sizeof x);
+        x = _bswap64((uint64_t) (8 * mlen));
+        memcpy(&fb[8], &x, sizeof x);
+    }
+    /* we store H (and it's power) byte-reverted once and for all */
+    Hv = _mm_shuffle_epi8(_mm_load_si128((const __m128i *) H), rev);
+    _mm_store_si128((__m128i *) H, Hv);
+    H2v = mulv(Hv, Hv);
+    H3v = mulv(H2v, Hv);
+    H4v = mulv(H3v, Hv);
+
+    accv = _mm_setzero_si128();
+    /* unrolled by 4 GCM (by 8 doesn't improve using MULREDUCE4) */
+    for (i = 0; i < adlen_rnd64; i += 64) {
+        __m128i X4_ = _mm_loadu_si128((const __m128i *) (ad + i + 0));
+        __m128i X3_ = _mm_loadu_si128((const __m128i *) (ad + i + 16));
+        __m128i X2_ = _mm_loadu_si128((const __m128i *) (ad + i + 32));
+        __m128i X1_ = _mm_loadu_si128((const __m128i *) (ad + i + 48));
+        MULREDUCE4(rev, Hv, H2v, H3v, H4v, X1_, X2_, X3_, X4_, accv);
+    }
+    _mm_store_si128((__m128i *) accum, accv);
+
+    /* GCM remainder loop */
+    for (i = adlen_rnd64; i < adlen; i += 16) {
+        unsigned int blocklen = 16;
+
+        if (i + (unsigned long long) blocklen > adlen) {
+            blocklen = (unsigned int) (adlen - i);
+        }
+        addmul(accum, ad + i, blocklen, H);
+    }
+
+/* this only does 8 full blocks, so no fancy bounds checking is necessary*/
+#define LOOPRND128                                                                                   \
+    do {                                                                                             \
+        const int iter = 8;                                                                          \
+        const int lb = iter * 16;                                                                    \
+                                                                                                     \
+        for (i = 0; i < mlen_rnd128; i += lb) {                                                      \
+            aesni_encrypt8full(c + i, n2, rkeys, m + i, accum, Hv, H2v, H3v, H4v, rev);              \
+        }                                                                                            \
+    } while(0)
+
+/* remainder loop, with the slower GCM update to accommodate partial blocks */
+#define LOOPRMD128                                           \
+    do {                                                     \
+        const int iter = 8;                                  \
+        const int lb = iter * 16;                            \
+                                                             \
+        for (i = mlen_rnd128; i < mlen; i += lb) {           \
+            CRYPTO_ALIGN(16) unsigned char outni[8 * 16];    \
+            unsigned long long mj = lb;                      \
+                                                             \
+            aesni_encrypt8(outni, n2, rkeys);                \
+            if ((i + mj) >= mlen) {                          \
+                mj = mlen - i;                               \
+            }                                                \
+            for (j = 0; j < mj; j++) {                       \
+                c[i + j] = m[i + j] ^ outni[j];              \
+            }                                                \
+            for (j = 0; j < mj; j += 16) {                   \
+                unsigned int bl = 16;                        \
+                                                             \
+                if (j + (unsigned long long) bl >= mj) {     \
+                    bl = (unsigned int) (mj - j);            \
+                }                                            \
+                addmul(accum, c + i + j, bl, H);             \
+            }                                                \
+        }                                                    \
+    } while(0)
+
+    n2[3] &= 0x00ffffff;
+    COUNTER_INC2(n2);
+    LOOPRND128;
+    LOOPRMD128;
+
+    addmul(accum, fb, 16, H);
+
+    for (i = 0; i < 16; ++i) {
+        mac[i] = T[i] ^ accum[15 - i];
+    }
+    if (maclen_p != NULL) {
+        *maclen_p = 16;
+    }
+    return 0;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_afternm(unsigned char *c, unsigned long long *clen_p,
+                                      const unsigned char *m, unsigned long long mlen,
+                                      const unsigned char *ad, unsigned long long adlen,
+                                      const unsigned char *nsec,
+                                      const unsigned char *npub,
+                                      const crypto_aead_aes256gcm_state *ctx_)
+{
+    int ret = crypto_aead_aes256gcm_encrypt_detached_afternm(c,
+                                                             c + mlen, NULL,
+                                                             m, mlen,
+                                                             ad, adlen,
+                                                             nsec, npub, ctx_);
+    if (clen_p != NULL) {
+        *clen_p = mlen + crypto_aead_aes256gcm_ABYTES;
+    }
+    return ret;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached_afternm(unsigned char *m, unsigned char *nsec,
+                                               const unsigned char *c, unsigned long long clen,
+                                               const unsigned char *mac,
+                                               const unsigned char *ad, unsigned long long adlen,
+                                               const unsigned char *npub,
+                                               const crypto_aead_aes256gcm_state *ctx_)
+{
+    const __m128i          rev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+    const aes256gcm_state *ctx = (const aes256gcm_state *) (const void *) ctx_;
+    const __m128i         *rkeys = ctx->rkeys;
+    __m128i                Hv, H2v, H3v, H4v, accv;
+    unsigned long long     i, j;
+    unsigned long long     adlen_rnd64 = adlen & ~63ULL;
+    unsigned long long     mlen;
+    unsigned long long     mlen_rnd128;
+    CRYPTO_ALIGN(16) uint32_t      n2[4];
+    CRYPTO_ALIGN(16) unsigned char H[16];
+    CRYPTO_ALIGN(16) unsigned char T[16];
+    CRYPTO_ALIGN(16) unsigned char accum[16];
+    CRYPTO_ALIGN(16) unsigned char fb[16];
+
+    (void) nsec;
+    if (clen > crypto_aead_aes256gcm_MESSAGEBYTES_MAX) {
+        sodium_misuse(); /* LCOV_EXCL_LINE */
+    }
+    mlen = clen;
+
+    memcpy(&n2[0], npub, 3 * 4);
+    n2[3] = 0x01000000;
+    aesni_encrypt1(T, _mm_load_si128((const __m128i *) n2), rkeys);
+
+    {
+        uint64_t x;
+        x = _bswap64((uint64_t)(8 * adlen));
+        memcpy(&fb[0], &x, sizeof x);
+        x = _bswap64((uint64_t)(8 * mlen));
+        memcpy(&fb[8], &x, sizeof x);
+    }
+
+    memcpy(H, ctx->H, sizeof H);
+    Hv = _mm_shuffle_epi8(_mm_load_si128((const __m128i *) H), rev);
+    _mm_store_si128((__m128i *) H, Hv);
+    H2v = mulv(Hv, Hv);
+    H3v = mulv(H2v, Hv);
+    H4v = mulv(H3v, Hv);
+
+    accv = _mm_setzero_si128();
+    for (i = 0; i < adlen_rnd64; i += 64) {
+        __m128i X4_ = _mm_loadu_si128((const __m128i *) (ad + i + 0));
+        __m128i X3_ = _mm_loadu_si128((const __m128i *) (ad + i + 16));
+        __m128i X2_ = _mm_loadu_si128((const __m128i *) (ad + i + 32));
+        __m128i X1_ = _mm_loadu_si128((const __m128i *) (ad + i + 48));
+        MULREDUCE4(rev, Hv, H2v, H3v, H4v, X1_, X2_, X3_, X4_, accv);
+    }
+    _mm_store_si128((__m128i *) accum, accv);
+
+    for (i = adlen_rnd64; i < adlen; i += 16) {
+        unsigned int blocklen = 16;
+        if (i + (unsigned long long) blocklen > adlen) {
+            blocklen = (unsigned int) (adlen - i);
+        }
+        addmul(accum, ad + i, blocklen, H);
+    }
+
+    mlen_rnd128 = mlen & ~127ULL;
+
+#define LOOPACCUMDRND128                                                                          \
+    do {                                                                                          \
+        const int iter = 8;                                                                       \
+        const int lb = iter * 16;                                                                 \
+        for (i = 0; i < mlen_rnd128; i += lb) {                                                   \
+            aesni_addmul8full(c + i, accum, Hv, H2v, H3v, H4v, rev);                              \
+        }                                                                                         \
+    } while(0)
+
+#define LOOPDRND128                                                                               \
+    do {                                                                                          \
+        const int iter = 8;                                                                       \
+        const int lb = iter * 16;                                                                 \
+                                                                                                  \
+        for (i = 0; i < mlen_rnd128; i += lb) {                                                   \
+            aesni_decrypt8full(m + i, n2, rkeys, c + i);                                          \
+        }                                                                                         \
+    } while(0)
+
+#define LOOPACCUMDRMD128                                     \
+    do {                                                     \
+        const int iter = 8;                                  \
+        const int lb = iter * 16;                            \
+                                                             \
+        for (i = mlen_rnd128; i < mlen; i += lb) {           \
+            unsigned long long mj = lb;                      \
+                                                             \
+            if ((i + mj) >= mlen) {                          \
+                mj = mlen - i;                               \
+            }                                                \
+            for (j = 0; j < mj; j += 16) {                   \
+                unsigned int bl = 16;                        \
+                                                             \
+                if (j + (unsigned long long) bl >= mj) {     \
+                    bl = (unsigned int) (mj - j);            \
+                }                                            \
+                addmul(accum, c + i + j, bl, H);             \
+            }                                                \
+        }                                                    \
+    } while(0)
+
+#define LOOPDRMD128                                          \
+    do {                                                     \
+        const int iter = 8;                                  \
+        const int lb = iter * 16;                            \
+                                                             \
+        for (i = mlen_rnd128; i < mlen; i += lb) {           \
+            CRYPTO_ALIGN(16) unsigned char outni[8 * 16];    \
+            unsigned long long mj = lb;                      \
+                                                             \
+            if ((i + mj) >= mlen) {                          \
+                mj = mlen - i;                               \
+            }                                                \
+            aesni_encrypt8(outni, n2, rkeys);                \
+            for (j = 0; j < mj; j++) {                       \
+                m[i + j] = c[i + j] ^ outni[j];              \
+            }                                                \
+        }                                                    \
+    } while(0)
+
+    n2[3] &= 0x00ffffff;
+
+    COUNTER_INC2(n2);
+    LOOPACCUMDRND128;
+    LOOPACCUMDRMD128;
+    addmul(accum, fb, 16, H);
+    {
+        unsigned char d = 0;
+
+        for (i = 0; i < 16; i++) {
+            d |= (mac[i] ^ (T[i] ^ accum[15 - i]));
+        }
+        if (d != 0) {
+            if (m != NULL) {
+                memset(m, 0, mlen);
+            }
+            return -1;
+        }
+        if (m == NULL) {
+            return 0;
+        }
+    }
+    n2[3] = 0U;
+    COUNTER_INC2(n2);
+    LOOPDRND128;
+    LOOPDRMD128;
+
+    return 0;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_afternm(unsigned char *m, unsigned long long *mlen_p,
+                                      unsigned char *nsec,
+                                      const unsigned char *c, unsigned long long clen,
+                                      const unsigned char *ad, unsigned long long adlen,
+                                      const unsigned char *npub,
+                                      const crypto_aead_aes256gcm_state *ctx_)
+{
+    unsigned long long mlen = 0ULL;
+    int                ret = -1;
+
+    if (clen >= crypto_aead_aes256gcm_ABYTES) {
+        ret = crypto_aead_aes256gcm_decrypt_detached_afternm
+            (m, nsec, c, clen - crypto_aead_aes256gcm_ABYTES,
+             c + clen - crypto_aead_aes256gcm_ABYTES,
+             ad, adlen, npub, ctx_);
+    }
+    if (mlen_p != NULL) {
+        if (ret == 0) {
+            mlen = clen - crypto_aead_aes256gcm_ABYTES;
+        }
+        *mlen_p = mlen;
+    }
+    return ret;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_detached(unsigned char *c,
+                                       unsigned char *mac,
+                                       unsigned long long *maclen_p,
+                                       const unsigned char *m,
+                                       unsigned long long mlen,
+                                       const unsigned char *ad,
+                                       unsigned long long adlen,
+                                       const unsigned char *nsec,
+                                       const unsigned char *npub,
+                                       const unsigned char *k)
+{
+    CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+
+    crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+    return crypto_aead_aes256gcm_encrypt_detached_afternm
+        (c, mac, maclen_p, m, mlen, ad, adlen, nsec, npub,
+            (const crypto_aead_aes256gcm_state *) &ctx);
+}
+
+int
+crypto_aead_aes256gcm_encrypt(unsigned char *c,
+                              unsigned long long *clen_p,
+                              const unsigned char *m,
+                              unsigned long long mlen,
+                              const unsigned char *ad,
+                              unsigned long long adlen,
+                              const unsigned char *nsec,
+                              const unsigned char *npub,
+                              const unsigned char *k)
+{
+    CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+    int ret;
+
+    crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+    ret = crypto_aead_aes256gcm_encrypt_afternm
+        (c, clen_p, m, mlen, ad, adlen, nsec, npub,
+            (const crypto_aead_aes256gcm_state *) &ctx);
+    sodium_memzero(&ctx, sizeof ctx);
+
+    return ret;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached(unsigned char *m,
+                                       unsigned char *nsec,
+                                       const unsigned char *c,
+                                       unsigned long long clen,
+                                       const unsigned char *mac,
+                                       const unsigned char *ad,
+                                       unsigned long long adlen,
+                                       const unsigned char *npub,
+                                       const unsigned char *k)
+{
+    CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+
+    crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+    return crypto_aead_aes256gcm_decrypt_detached_afternm
+        (m, nsec, c, clen, mac, ad, adlen, npub,
+            (const crypto_aead_aes256gcm_state *) &ctx);
+}
+
+int
+crypto_aead_aes256gcm_decrypt(unsigned char *m,
+                              unsigned long long *mlen_p,
+                              unsigned char *nsec,
+                              const unsigned char *c,
+                              unsigned long long clen,
+                              const unsigned char *ad,
+                              unsigned long long adlen,
+                              const unsigned char *npub,
+                              const unsigned char *k)
+{
+    CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+    int ret;
+
+    crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+    ret = crypto_aead_aes256gcm_decrypt_afternm
+        (m, mlen_p, nsec, c, clen, ad, adlen, npub,
+         (const crypto_aead_aes256gcm_state *) &ctx);
+    sodium_memzero(&ctx, sizeof ctx);
+
+    return ret;
+}
+
+int
+crypto_aead_aes256gcm_is_available(void)
+{
+    return sodium_runtime_has_pclmul() & sodium_runtime_has_aesni();
+}
+
+#else
+
+int
+crypto_aead_aes256gcm_encrypt_detached(unsigned char *c,
+                                       unsigned char *mac,
+                                       unsigned long long *maclen_p,
+                                       const unsigned char *m,
+                                       unsigned long long mlen,
+                                       const unsigned char *ad,
+                                       unsigned long long adlen,
+                                       const unsigned char *nsec,
+                                       const unsigned char *npub,
+                                       const unsigned char *k)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_encrypt(unsigned char *c, unsigned long long *clen_p,
+                              const unsigned char *m, unsigned long long mlen,
+                              const unsigned char *ad, unsigned long long adlen,
+                              const unsigned char *nsec, const unsigned char *npub,
+                              const unsigned char *k)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached(unsigned char *m,
+                                       unsigned char *nsec,
+                                       const unsigned char *c,
+                                       unsigned long long clen,
+                                       const unsigned char *mac,
+                                       const unsigned char *ad,
+                                       unsigned long long adlen,
+                                       const unsigned char *npub,
+                                       const unsigned char *k)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt(unsigned char *m, unsigned long long *mlen_p,
+                              unsigned char *nsec, const unsigned char *c,
+                              unsigned long long clen, const unsigned char *ad,
+                              unsigned long long adlen, const unsigned char *npub,
+                              const unsigned char *k)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_beforenm(crypto_aead_aes256gcm_state *ctx_,
+                               const unsigned char *k)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_detached_afternm(unsigned char *c,
+                                               unsigned char *mac, unsigned long long *maclen_p,
+                                               const unsigned char *m, unsigned long long mlen,
+                                               const unsigned char *ad, unsigned long long adlen,
+                                               const unsigned char *nsec,
+                                               const unsigned char *npub,
+                                               const crypto_aead_aes256gcm_state *ctx_)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_afternm(unsigned char *c, unsigned long long *clen_p,
+                                      const unsigned char *m, unsigned long long mlen,
+                                      const unsigned char *ad, unsigned long long adlen,
+                                      const unsigned char *nsec, const unsigned char *npub,
+                                      const crypto_aead_aes256gcm_state *ctx_)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached_afternm(unsigned char *m, unsigned char *nsec,
+                                               const unsigned char *c, unsigned long long clen,
+                                               const unsigned char *mac,
+                                               const unsigned char *ad, unsigned long long adlen,
+                                               const unsigned char *npub,
+                                               const crypto_aead_aes256gcm_state *ctx_)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_afternm(unsigned char *m, unsigned long long *mlen_p,
+                                      unsigned char *nsec,
+                                      const unsigned char *c, unsigned long long clen,
+                                      const unsigned char *ad, unsigned long long adlen,
+                                      const unsigned char *npub,
+                                      const crypto_aead_aes256gcm_state *ctx_)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+crypto_aead_aes256gcm_is_available(void)
+{
+    return 0;
+}
+
+#endif
+
+size_t
+crypto_aead_aes256gcm_keybytes(void)
+{
+    return crypto_aead_aes256gcm_KEYBYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_nsecbytes(void)
+{
+    return crypto_aead_aes256gcm_NSECBYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_npubbytes(void)
+{
+    return crypto_aead_aes256gcm_NPUBBYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_abytes(void)
+{
+    return crypto_aead_aes256gcm_ABYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_statebytes(void)
+{
+    return (sizeof(crypto_aead_aes256gcm_state) + (size_t) 15U) & ~(size_t) 15U;
+}
+
+size_t
+crypto_aead_aes256gcm_messagebytes_max(void)
+{
+    return crypto_aead_aes256gcm_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_aes256gcm_keygen(unsigned char k[crypto_aead_aes256gcm_KEYBYTES])
+{
+    randombytes_buf(k, crypto_aead_aes256gcm_KEYBYTES);
+}

+ 400 - 0
Sources/Sodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c

@@ -0,0 +1,400 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_chacha20poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_verify_16.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#include "private/chacha20_ietf_ext.h"
+#include "private/common.h"
+
+static const unsigned char _pad0[16] = { 0 };
+
+int
+crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c,
+                                              unsigned char *mac,
+                                              unsigned long long *maclen_p,
+                                              const unsigned char *m,
+                                              unsigned long long mlen,
+                                              const unsigned char *ad,
+                                              unsigned long long adlen,
+                                              const unsigned char *nsec,
+                                              const unsigned char *npub,
+                                              const unsigned char *k)
+{
+    crypto_onetimeauth_poly1305_state state;
+    unsigned char                     block0[64U];
+    unsigned char                     slen[8U];
+
+    (void) nsec;
+    crypto_stream_chacha20(block0, sizeof block0, npub, k);
+    crypto_onetimeauth_poly1305_init(&state, block0);
+    sodium_memzero(block0, sizeof block0);
+
+    crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+    STORE64_LE(slen, (uint64_t) adlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
+
+    crypto_onetimeauth_poly1305_update(&state, c, mlen);
+    STORE64_LE(slen, (uint64_t) mlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_onetimeauth_poly1305_final(&state, mac);
+    sodium_memzero(&state, sizeof state);
+
+    if (maclen_p != NULL) {
+        *maclen_p = crypto_aead_chacha20poly1305_ABYTES;
+    }
+    return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
+                                     unsigned long long *clen_p,
+                                     const unsigned char *m,
+                                     unsigned long long mlen,
+                                     const unsigned char *ad,
+                                     unsigned long long adlen,
+                                     const unsigned char *nsec,
+                                     const unsigned char *npub,
+                                     const unsigned char *k)
+{
+    unsigned long long clen = 0ULL;
+    int                ret;
+
+    if (mlen > crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    ret = crypto_aead_chacha20poly1305_encrypt_detached(c,
+                                                        c + mlen, NULL,
+                                                        m, mlen,
+                                                        ad, adlen,
+                                                        nsec, npub, k);
+    if (clen_p != NULL) {
+        if (ret == 0) {
+            clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
+        }
+        *clen_p = clen;
+    }
+    return ret;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c,
+                                                   unsigned char *mac,
+                                                   unsigned long long *maclen_p,
+                                                   const unsigned char *m,
+                                                   unsigned long long mlen,
+                                                   const unsigned char *ad,
+                                                   unsigned long long adlen,
+                                                   const unsigned char *nsec,
+                                                   const unsigned char *npub,
+                                                   const unsigned char *k)
+{
+    crypto_onetimeauth_poly1305_state state;
+    unsigned char                     block0[64U];
+    unsigned char                     slen[8U];
+
+    (void) nsec;
+    crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
+    crypto_onetimeauth_poly1305_init(&state, block0);
+    sodium_memzero(block0, sizeof block0);
+
+    crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
+
+    crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k);
+
+    crypto_onetimeauth_poly1305_update(&state, c, mlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
+
+    STORE64_LE(slen, (uint64_t) adlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    STORE64_LE(slen, (uint64_t) mlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_onetimeauth_poly1305_final(&state, mac);
+    sodium_memzero(&state, sizeof state);
+
+    if (maclen_p != NULL) {
+        *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
+    }
+    return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c,
+                                          unsigned long long *clen_p,
+                                          const unsigned char *m,
+                                          unsigned long long mlen,
+                                          const unsigned char *ad,
+                                          unsigned long long adlen,
+                                          const unsigned char *nsec,
+                                          const unsigned char *npub,
+                                          const unsigned char *k)
+{
+    unsigned long long clen = 0ULL;
+    int                ret;
+
+    if (mlen > crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c,
+                                                             c + mlen, NULL,
+                                                             m, mlen,
+                                                             ad, adlen,
+                                                             nsec, npub, k);
+    if (clen_p != NULL) {
+        if (ret == 0) {
+            clen = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES;
+        }
+        *clen_p = clen;
+    }
+    return ret;
+}
+
+int
+crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m,
+                                              unsigned char *nsec,
+                                              const unsigned char *c,
+                                              unsigned long long clen,
+                                              const unsigned char *mac,
+                                              const unsigned char *ad,
+                                              unsigned long long adlen,
+                                              const unsigned char *npub,
+                                              const unsigned char *k)
+{
+    crypto_onetimeauth_poly1305_state state;
+    unsigned char                     block0[64U];
+    unsigned char                     slen[8U];
+    unsigned char                     computed_mac[crypto_aead_chacha20poly1305_ABYTES];
+    unsigned long long                mlen;
+    int                               ret;
+
+    (void) nsec;
+    crypto_stream_chacha20(block0, sizeof block0, npub, k);
+    crypto_onetimeauth_poly1305_init(&state, block0);
+    sodium_memzero(block0, sizeof block0);
+
+    crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+    STORE64_LE(slen, (uint64_t) adlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    mlen = clen;
+    crypto_onetimeauth_poly1305_update(&state, c, mlen);
+    STORE64_LE(slen, (uint64_t) mlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_onetimeauth_poly1305_final(&state, computed_mac);
+    sodium_memzero(&state, sizeof state);
+
+    COMPILER_ASSERT(sizeof computed_mac == 16U);
+    ret = crypto_verify_16(computed_mac, mac);
+    sodium_memzero(computed_mac, sizeof computed_mac);
+    if (m == NULL) {
+        return ret;
+    }
+    if (ret != 0) {
+        memset(m, 0, mlen);
+        return -1;
+    }
+    crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k);
+
+    return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
+                                     unsigned long long *mlen_p,
+                                     unsigned char *nsec,
+                                     const unsigned char *c,
+                                     unsigned long long clen,
+                                     const unsigned char *ad,
+                                     unsigned long long adlen,
+                                     const unsigned char *npub,
+                                     const unsigned char *k)
+{
+    unsigned long long mlen = 0ULL;
+    int                ret = -1;
+
+    if (clen >= crypto_aead_chacha20poly1305_ABYTES) {
+        ret = crypto_aead_chacha20poly1305_decrypt_detached
+            (m, nsec,
+             c, clen - crypto_aead_chacha20poly1305_ABYTES,
+             c + clen - crypto_aead_chacha20poly1305_ABYTES,
+             ad, adlen, npub, k);
+    }
+    if (mlen_p != NULL) {
+        if (ret == 0) {
+            mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
+        }
+        *mlen_p = mlen;
+    }
+    return ret;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m,
+                                                   unsigned char *nsec,
+                                                   const unsigned char *c,
+                                                   unsigned long long clen,
+                                                   const unsigned char *mac,
+                                                   const unsigned char *ad,
+                                                   unsigned long long adlen,
+                                                   const unsigned char *npub,
+                                                   const unsigned char *k)
+{
+    crypto_onetimeauth_poly1305_state state;
+    unsigned char                     block0[64U];
+    unsigned char                     slen[8U];
+    unsigned char                     computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
+    unsigned long long                mlen;
+    int                               ret;
+
+    (void) nsec;
+    crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
+    crypto_onetimeauth_poly1305_init(&state, block0);
+    sodium_memzero(block0, sizeof block0);
+
+    crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
+
+    mlen = clen;
+    crypto_onetimeauth_poly1305_update(&state, c, mlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
+
+    STORE64_LE(slen, (uint64_t) adlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    STORE64_LE(slen, (uint64_t) mlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_onetimeauth_poly1305_final(&state, computed_mac);
+    sodium_memzero(&state, sizeof state);
+
+    COMPILER_ASSERT(sizeof computed_mac == 16U);
+    ret = crypto_verify_16(computed_mac, mac);
+    sodium_memzero(computed_mac, sizeof computed_mac);
+    if (m == NULL) {
+        return ret;
+    }
+    if (ret != 0) {
+        memset(m, 0, mlen);
+        return -1;
+    }
+    crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k);
+
+    return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m,
+                                          unsigned long long *mlen_p,
+                                          unsigned char *nsec,
+                                          const unsigned char *c,
+                                          unsigned long long clen,
+                                          const unsigned char *ad,
+                                          unsigned long long adlen,
+                                          const unsigned char *npub,
+                                          const unsigned char *k)
+{
+    unsigned long long mlen = 0ULL;
+    int                ret = -1;
+
+    if (clen >= crypto_aead_chacha20poly1305_ietf_ABYTES) {
+        ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
+            (m, nsec,
+             c, clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
+             c + clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
+             ad, adlen, npub, k);
+    }
+    if (mlen_p != NULL) {
+        if (ret == 0) {
+            mlen = clen - crypto_aead_chacha20poly1305_ietf_ABYTES;
+        }
+        *mlen_p = mlen;
+    }
+    return ret;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_keybytes(void)
+{
+    return crypto_aead_chacha20poly1305_ietf_KEYBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_npubbytes(void)
+{
+    return crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_nsecbytes(void)
+{
+    return crypto_aead_chacha20poly1305_ietf_NSECBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_abytes(void)
+{
+    return crypto_aead_chacha20poly1305_ietf_ABYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_messagebytes_max(void)
+{
+    return crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES])
+{
+    randombytes_buf(k, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
+}
+
+size_t
+crypto_aead_chacha20poly1305_keybytes(void)
+{
+    return crypto_aead_chacha20poly1305_KEYBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_npubbytes(void)
+{
+    return crypto_aead_chacha20poly1305_NPUBBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_nsecbytes(void)
+{
+    return crypto_aead_chacha20poly1305_NSECBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_abytes(void)
+{
+    return crypto_aead_chacha20poly1305_ABYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_messagebytes_max(void)
+{
+    return crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES])
+{
+    randombytes_buf(k, crypto_aead_chacha20poly1305_KEYBYTES);
+}

+ 262 - 0
Sources/Sodium/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c

@@ -0,0 +1,262 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_chacha20poly1305.h"
+#include "crypto_aead_xchacha20poly1305.h"
+#include "crypto_core_hchacha20.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_verify_16.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#include "private/chacha20_ietf_ext.h"
+#include "private/common.h"
+
+static const unsigned char _pad0[16] = { 0 };
+
+static int
+_encrypt_detached(unsigned char *c,
+                  unsigned char *mac,
+                  unsigned long long *maclen_p,
+                  const unsigned char *m,
+                  unsigned long long mlen,
+                  const unsigned char *ad,
+                  unsigned long long adlen,
+                  const unsigned char *nsec,
+                  const unsigned char *npub,
+                  const unsigned char *k)
+{
+    crypto_onetimeauth_poly1305_state state;
+    unsigned char                     block0[64U];
+    unsigned char                     slen[8U];
+
+    (void) nsec;
+    crypto_stream_chacha20_ietf_ext(block0, sizeof block0, npub, k);
+    crypto_onetimeauth_poly1305_init(&state, block0);
+    sodium_memzero(block0, sizeof block0);
+
+    crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
+
+    crypto_stream_chacha20_ietf_ext_xor_ic(c, m, mlen, npub, 1U, k);
+
+    crypto_onetimeauth_poly1305_update(&state, c, mlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
+
+    STORE64_LE(slen, (uint64_t) adlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    STORE64_LE(slen, (uint64_t) mlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_onetimeauth_poly1305_final(&state, mac);
+    sodium_memzero(&state, sizeof state);
+
+    if (maclen_p != NULL) {
+        *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
+    }
+    return 0;
+}
+
+static int
+_decrypt_detached(unsigned char *m,
+                  unsigned char *nsec,
+                  const unsigned char *c,
+                  unsigned long long clen,
+                  const unsigned char *mac,
+                  const unsigned char *ad,
+                  unsigned long long adlen,
+                  const unsigned char *npub,
+                  const unsigned char *k)
+{
+    crypto_onetimeauth_poly1305_state state;
+    unsigned char                     block0[64U];
+    unsigned char                     slen[8U];
+    unsigned char                     computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
+    unsigned long long                mlen;
+    int                               ret;
+
+    (void) nsec;
+    crypto_stream_chacha20_ietf_ext(block0, sizeof block0, npub, k);
+    crypto_onetimeauth_poly1305_init(&state, block0);
+    sodium_memzero(block0, sizeof block0);
+
+    crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
+
+    mlen = clen;
+    crypto_onetimeauth_poly1305_update(&state, c, mlen);
+    crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
+
+    STORE64_LE(slen, (uint64_t) adlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    STORE64_LE(slen, (uint64_t) mlen);
+    crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+    crypto_onetimeauth_poly1305_final(&state, computed_mac);
+    sodium_memzero(&state, sizeof state);
+
+    COMPILER_ASSERT(sizeof computed_mac == 16U);
+    ret = crypto_verify_16(computed_mac, mac);
+    sodium_memzero(computed_mac, sizeof computed_mac);
+    if (m == NULL) {
+        return ret;
+    }
+    if (ret != 0) {
+        memset(m, 0, mlen);
+        return -1;
+    }
+    crypto_stream_chacha20_ietf_ext_xor_ic(m, c, mlen, npub, 1U, k);
+
+    return 0;
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_encrypt_detached(unsigned char *c,
+                                                    unsigned char *mac,
+                                                    unsigned long long *maclen_p,
+                                                    const unsigned char *m,
+                                                    unsigned long long mlen,
+                                                    const unsigned char *ad,
+                                                    unsigned long long adlen,
+                                                    const unsigned char *nsec,
+                                                    const unsigned char *npub,
+                                                    const unsigned char *k)
+{
+    unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
+    unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
+    int           ret;
+
+    crypto_core_hchacha20(k2, npub, k, NULL);
+    memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
+           crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
+    ret = _encrypt_detached(c, mac, maclen_p, m, mlen, ad, adlen,
+                            nsec, npub2, k2);
+    sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
+
+    return ret;
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c,
+                                           unsigned long long *clen_p,
+                                           const unsigned char *m,
+                                           unsigned long long mlen,
+                                           const unsigned char *ad,
+                                           unsigned long long adlen,
+                                           const unsigned char *nsec,
+                                           const unsigned char *npub,
+                                           const unsigned char *k)
+{
+    unsigned long long clen = 0ULL;
+    int                ret;
+
+    if (mlen > crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached
+        (c, c + mlen, NULL, m, mlen, ad, adlen, nsec, npub, k);
+    if (clen_p != NULL) {
+        if (ret == 0) {
+            clen = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES;
+        }
+        *clen_p = clen;
+    }
+    return ret;
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_decrypt_detached(unsigned char *m,
+                                                    unsigned char *nsec,
+                                                    const unsigned char *c,
+                                                    unsigned long long clen,
+                                                    const unsigned char *mac,
+                                                    const unsigned char *ad,
+                                                    unsigned long long adlen,
+                                                    const unsigned char *npub,
+                                                    const unsigned char *k)
+{
+    unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
+    unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
+    int           ret;
+
+    crypto_core_hchacha20(k2, npub, k, NULL);
+    memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
+           crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
+    ret = _decrypt_detached(m, nsec, c, clen, mac, ad, adlen, npub2, k2);
+    sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
+
+    return ret;
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m,
+                                           unsigned long long *mlen_p,
+                                           unsigned char *nsec,
+                                           const unsigned char *c,
+                                           unsigned long long clen,
+                                           const unsigned char *ad,
+                                           unsigned long long adlen,
+                                           const unsigned char *npub,
+                                           const unsigned char *k)
+{
+    unsigned long long mlen = 0ULL;
+    int                ret  = -1;
+
+    if (clen >= crypto_aead_xchacha20poly1305_ietf_ABYTES) {
+        ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached
+            (m, nsec,
+             c, clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
+             c + clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
+             ad, adlen, npub, k);
+    }
+    if (mlen_p != NULL) {
+        if (ret == 0) {
+            mlen = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES;
+        }
+        *mlen_p = mlen;
+    }
+    return ret;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_keybytes(void)
+{
+    return crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_npubbytes(void)
+{
+    return crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_nsecbytes(void)
+{
+    return crypto_aead_xchacha20poly1305_ietf_NSECBYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_abytes(void)
+{
+    return crypto_aead_xchacha20poly1305_ietf_ABYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_messagebytes_max(void)
+{
+    return crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES])
+{
+    randombytes_buf(k, crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
+}

+ 41 - 0
Sources/Sodium/crypto_auth/crypto_auth.c

@@ -0,0 +1,41 @@
+
+#include "crypto_auth.h"
+#include "randombytes.h"
+
+size_t
+crypto_auth_bytes(void)
+{
+    return crypto_auth_BYTES;
+}
+
+size_t
+crypto_auth_keybytes(void)
+{
+    return crypto_auth_KEYBYTES;
+}
+
+const char *
+crypto_auth_primitive(void)
+{
+    return crypto_auth_PRIMITIVE;
+}
+
+int
+crypto_auth(unsigned char *out, const unsigned char *in,
+            unsigned long long inlen, const unsigned char *k)
+{
+    return crypto_auth_hmacsha512256(out, in, inlen, k);
+}
+
+int
+crypto_auth_verify(const unsigned char *h, const unsigned char *in,
+                   unsigned long long inlen,const unsigned char *k)
+{
+    return crypto_auth_hmacsha512256_verify(h, in, inlen, k);
+}
+
+void
+crypto_auth_keygen(unsigned char k[crypto_auth_KEYBYTES])
+{
+    randombytes_buf(k, crypto_auth_KEYBYTES);
+}

+ 118 - 0
Sources/Sodium/crypto_auth/hmacsha256/auth_hmacsha256.c

@@ -0,0 +1,118 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha256.h"
+#include "crypto_hash_sha256.h"
+#include "crypto_verify_32.h"
+#include "randombytes.h"
+#include "utils.h"
+
+size_t
+crypto_auth_hmacsha256_bytes(void)
+{
+    return crypto_auth_hmacsha256_BYTES;
+}
+
+size_t
+crypto_auth_hmacsha256_keybytes(void)
+{
+    return crypto_auth_hmacsha256_KEYBYTES;
+}
+
+size_t
+crypto_auth_hmacsha256_statebytes(void)
+{
+    return sizeof(crypto_auth_hmacsha256_state);
+}
+
+void
+crypto_auth_hmacsha256_keygen(unsigned char k[crypto_auth_hmacsha256_KEYBYTES])
+{
+    randombytes_buf(k, crypto_auth_hmacsha256_KEYBYTES);
+}
+
+int
+crypto_auth_hmacsha256_init(crypto_auth_hmacsha256_state *state,
+                            const unsigned char *key, size_t keylen)
+{
+    unsigned char pad[64];
+    unsigned char khash[32];
+    size_t        i;
+
+    if (keylen > 64) {
+        crypto_hash_sha256_init(&state->ictx);
+        crypto_hash_sha256_update(&state->ictx, key, keylen);
+        crypto_hash_sha256_final(&state->ictx, khash);
+        key    = khash;
+        keylen = 32;
+    }
+    crypto_hash_sha256_init(&state->ictx);
+    memset(pad, 0x36, 64);
+    for (i = 0; i < keylen; i++) {
+        pad[i] ^= key[i];
+    }
+    crypto_hash_sha256_update(&state->ictx, pad, 64);
+
+    crypto_hash_sha256_init(&state->octx);
+    memset(pad, 0x5c, 64);
+    for (i = 0; i < keylen; i++) {
+        pad[i] ^= key[i];
+    }
+    crypto_hash_sha256_update(&state->octx, pad, 64);
+
+    sodium_memzero((void *) pad, sizeof pad);
+    sodium_memzero((void *) khash, sizeof khash);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha256_update(crypto_auth_hmacsha256_state *state,
+                              const unsigned char *in, unsigned long long inlen)
+{
+    crypto_hash_sha256_update(&state->ictx, in, inlen);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha256_final(crypto_auth_hmacsha256_state *state,
+                             unsigned char                *out)
+{
+    unsigned char ihash[32];
+
+    crypto_hash_sha256_final(&state->ictx, ihash);
+    crypto_hash_sha256_update(&state->octx, ihash, 32);
+    crypto_hash_sha256_final(&state->octx, out);
+
+    sodium_memzero((void *) ihash, sizeof ihash);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha256(unsigned char *out, const unsigned char *in,
+                       unsigned long long inlen, const unsigned char *k)
+{
+    crypto_auth_hmacsha256_state state;
+
+    crypto_auth_hmacsha256_init(&state, k, crypto_auth_hmacsha256_KEYBYTES);
+    crypto_auth_hmacsha256_update(&state, in, inlen);
+    crypto_auth_hmacsha256_final(&state, out);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha256_verify(const unsigned char *h, const unsigned char *in,
+                              unsigned long long inlen, const unsigned char *k)
+{
+    unsigned char correct[32];
+
+    crypto_auth_hmacsha256(correct, in, inlen, k);
+
+    return crypto_verify_32(h, correct) | (-(h == correct)) |
+           sodium_memcmp(correct, h, 32);
+}

+ 118 - 0
Sources/Sodium/crypto_auth/hmacsha512/auth_hmacsha512.c

@@ -0,0 +1,118 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha512.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_64.h"
+#include "randombytes.h"
+#include "utils.h"
+
+size_t
+crypto_auth_hmacsha512_bytes(void)
+{
+    return crypto_auth_hmacsha512_BYTES;
+}
+
+size_t
+crypto_auth_hmacsha512_keybytes(void)
+{
+    return crypto_auth_hmacsha512_KEYBYTES;
+}
+
+size_t
+crypto_auth_hmacsha512_statebytes(void)
+{
+    return sizeof(crypto_auth_hmacsha512_state);
+}
+
+void
+crypto_auth_hmacsha512_keygen(unsigned char k[crypto_auth_hmacsha512_KEYBYTES])
+{
+    randombytes_buf(k, crypto_auth_hmacsha512_KEYBYTES);
+}
+
+int
+crypto_auth_hmacsha512_init(crypto_auth_hmacsha512_state *state,
+                            const unsigned char *key, size_t keylen)
+{
+    unsigned char pad[128];
+    unsigned char khash[64];
+    size_t        i;
+
+    if (keylen > 128) {
+        crypto_hash_sha512_init(&state->ictx);
+        crypto_hash_sha512_update(&state->ictx, key, keylen);
+        crypto_hash_sha512_final(&state->ictx, khash);
+        key    = khash;
+        keylen = 64;
+    }
+    crypto_hash_sha512_init(&state->ictx);
+    memset(pad, 0x36, 128);
+    for (i = 0; i < keylen; i++) {
+        pad[i] ^= key[i];
+    }
+    crypto_hash_sha512_update(&state->ictx, pad, 128);
+
+    crypto_hash_sha512_init(&state->octx);
+    memset(pad, 0x5c, 128);
+    for (i = 0; i < keylen; i++) {
+        pad[i] ^= key[i];
+    }
+    crypto_hash_sha512_update(&state->octx, pad, 128);
+
+    sodium_memzero((void *) pad, sizeof pad);
+    sodium_memzero((void *) khash, sizeof khash);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha512_update(crypto_auth_hmacsha512_state *state,
+                              const unsigned char *in, unsigned long long inlen)
+{
+    crypto_hash_sha512_update(&state->ictx, in, inlen);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha512_final(crypto_auth_hmacsha512_state *state,
+                             unsigned char                *out)
+{
+    unsigned char ihash[64];
+
+    crypto_hash_sha512_final(&state->ictx, ihash);
+    crypto_hash_sha512_update(&state->octx, ihash, 64);
+    crypto_hash_sha512_final(&state->octx, out);
+
+    sodium_memzero((void *) ihash, sizeof ihash);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha512(unsigned char *out, const unsigned char *in,
+                       unsigned long long inlen, const unsigned char *k)
+{
+    crypto_auth_hmacsha512_state state;
+
+    crypto_auth_hmacsha512_init(&state, k, crypto_auth_hmacsha512_KEYBYTES);
+    crypto_auth_hmacsha512_update(&state, in, inlen);
+    crypto_auth_hmacsha512_final(&state, out);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha512_verify(const unsigned char *h, const unsigned char *in,
+                              unsigned long long inlen, const unsigned char *k)
+{
+    unsigned char correct[64];
+
+    crypto_auth_hmacsha512(correct, in, inlen, k);
+
+    return crypto_verify_64(h, correct) | (-(h == correct)) |
+           sodium_memcmp(correct, h, 64);
+}

+ 93 - 0
Sources/Sodium/crypto_auth/hmacsha512256/auth_hmacsha512256.c

@@ -0,0 +1,93 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha512.h"
+#include "crypto_auth_hmacsha512256.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_32.h"
+#include "randombytes.h"
+#include "utils.h"
+
+size_t
+crypto_auth_hmacsha512256_bytes(void)
+{
+    return crypto_auth_hmacsha512256_BYTES;
+}
+
+size_t
+crypto_auth_hmacsha512256_keybytes(void)
+{
+    return crypto_auth_hmacsha512256_KEYBYTES;
+}
+
+size_t
+crypto_auth_hmacsha512256_statebytes(void)
+{
+    return sizeof(crypto_auth_hmacsha512256_state);
+}
+
+void
+crypto_auth_hmacsha512256_keygen(
+    unsigned char k[crypto_auth_hmacsha512256_KEYBYTES])
+{
+    randombytes_buf(k, crypto_auth_hmacsha512256_KEYBYTES);
+}
+
+int
+crypto_auth_hmacsha512256_init(crypto_auth_hmacsha512256_state *state,
+                               const unsigned char *key, size_t keylen)
+{
+    return crypto_auth_hmacsha512_init((crypto_auth_hmacsha512_state *) state,
+                                       key, keylen);
+}
+
+int
+crypto_auth_hmacsha512256_update(crypto_auth_hmacsha512256_state *state,
+                                 const unsigned char             *in,
+                                 unsigned long long               inlen)
+{
+    return crypto_auth_hmacsha512_update((crypto_auth_hmacsha512_state *) state,
+                                         in, inlen);
+}
+
+int
+crypto_auth_hmacsha512256_final(crypto_auth_hmacsha512256_state *state,
+                                unsigned char                   *out)
+{
+    unsigned char out0[64];
+
+    crypto_auth_hmacsha512_final((crypto_auth_hmacsha512_state *) state, out0);
+    memcpy(out, out0, 32);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha512256(unsigned char *out, const unsigned char *in,
+                          unsigned long long inlen, const unsigned char *k)
+{
+    crypto_auth_hmacsha512256_state state;
+
+    crypto_auth_hmacsha512256_init(&state, k,
+                                   crypto_auth_hmacsha512256_KEYBYTES);
+    crypto_auth_hmacsha512256_update(&state, in, inlen);
+    crypto_auth_hmacsha512256_final(&state, out);
+
+    return 0;
+}
+
+int
+crypto_auth_hmacsha512256_verify(const unsigned char *h,
+                                 const unsigned char *in,
+                                 unsigned long long   inlen,
+                                 const unsigned char *k)
+{
+    unsigned char correct[32];
+
+    crypto_auth_hmacsha512256(correct, in, inlen, k);
+
+    return crypto_verify_32(h, correct) | (-(h == correct)) |
+           sodium_memcmp(correct, h, 32);
+}

+ 114 - 0
Sources/Sodium/crypto_box/crypto_box.c

@@ -0,0 +1,114 @@
+
+#include "crypto_box.h"
+
+size_t
+crypto_box_seedbytes(void)
+{
+    return crypto_box_SEEDBYTES;
+}
+
+size_t
+crypto_box_publickeybytes(void)
+{
+    return crypto_box_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_box_secretkeybytes(void)
+{
+    return crypto_box_SECRETKEYBYTES;
+}
+
+size_t
+crypto_box_beforenmbytes(void)
+{
+    return crypto_box_BEFORENMBYTES;
+}
+
+size_t
+crypto_box_noncebytes(void)
+{
+    return crypto_box_NONCEBYTES;
+}
+
+size_t
+crypto_box_zerobytes(void)
+{
+    return crypto_box_ZEROBYTES;
+}
+
+size_t
+crypto_box_boxzerobytes(void)
+{
+    return crypto_box_BOXZEROBYTES;
+}
+
+size_t
+crypto_box_macbytes(void)
+{
+    return crypto_box_MACBYTES;
+}
+
+size_t
+crypto_box_messagebytes_max(void)
+{
+    return crypto_box_MESSAGEBYTES_MAX;
+}
+
+const char *
+crypto_box_primitive(void)
+{
+    return crypto_box_PRIMITIVE;
+}
+
+int
+crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk,
+                        const unsigned char *seed)
+{
+    return crypto_box_curve25519xsalsa20poly1305_seed_keypair(pk, sk, seed);
+}
+
+int
+crypto_box_keypair(unsigned char *pk, unsigned char *sk)
+{
+    return crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk);
+}
+
+int
+crypto_box_beforenm(unsigned char *k, const unsigned char *pk,
+                    const unsigned char *sk)
+{
+    return crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk);
+}
+
+int
+crypto_box_afternm(unsigned char *c, const unsigned char *m,
+                   unsigned long long mlen, const unsigned char *n,
+                   const unsigned char *k)
+{
+    return crypto_box_curve25519xsalsa20poly1305_afternm(c, m, mlen, n, k);
+}
+
+int
+crypto_box_open_afternm(unsigned char *m, const unsigned char *c,
+                        unsigned long long clen, const unsigned char *n,
+                        const unsigned char *k)
+{
+    return crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k);
+}
+
+int
+crypto_box(unsigned char *c, const unsigned char *m,
+           unsigned long long mlen, const unsigned char *n,
+           const unsigned char *pk, const unsigned char *sk)
+{
+    return crypto_box_curve25519xsalsa20poly1305(c, m, mlen, n, pk, sk);
+}
+
+int
+crypto_box_open(unsigned char *m, const unsigned char *c,
+                unsigned long long clen, const unsigned char *n,
+                const unsigned char *pk, const unsigned char *sk)
+{
+    return crypto_box_curve25519xsalsa20poly1305_open(m, c, clen, n, pk, sk);
+}

+ 115 - 0
Sources/Sodium/crypto_box/crypto_box_easy.c

@@ -0,0 +1,115 @@
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "core.h"
+#include "crypto_box.h"
+#include "crypto_secretbox.h"
+#include "private/common.h"
+#include "utils.h"
+
+int
+crypto_box_detached_afternm(unsigned char *c, unsigned char *mac,
+                            const unsigned char *m, unsigned long long mlen,
+                            const unsigned char *n, const unsigned char *k)
+{
+    return crypto_secretbox_detached(c, mac, m, mlen, n, k);
+}
+
+int
+crypto_box_detached(unsigned char *c, unsigned char *mac,
+                    const unsigned char *m, unsigned long long mlen,
+                    const unsigned char *n, const unsigned char *pk,
+                    const unsigned char *sk)
+{
+    unsigned char k[crypto_box_BEFORENMBYTES];
+    int           ret;
+
+    COMPILER_ASSERT(crypto_box_BEFORENMBYTES >= crypto_secretbox_KEYBYTES);
+    if (crypto_box_beforenm(k, pk, sk) != 0) {
+        return -1;
+    }
+    ret = crypto_box_detached_afternm(c, mac, m, mlen, n, k);
+    sodium_memzero(k, sizeof k);
+
+    return ret;
+}
+
+int
+crypto_box_easy_afternm(unsigned char *c, const unsigned char *m,
+                        unsigned long long mlen, const unsigned char *n,
+                        const unsigned char *k)
+{
+    if (mlen > crypto_box_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    return crypto_box_detached_afternm(c + crypto_box_MACBYTES, c, m, mlen, n,
+                                       k);
+}
+
+int
+crypto_box_easy(unsigned char *c, const unsigned char *m,
+                unsigned long long mlen, const unsigned char *n,
+                const unsigned char *pk, const unsigned char *sk)
+{
+    if (mlen > crypto_box_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    return crypto_box_detached(c + crypto_box_MACBYTES, c, m, mlen, n,
+                               pk, sk);
+}
+
+int
+crypto_box_open_detached_afternm(unsigned char *m, const unsigned char *c,
+                                 const unsigned char *mac,
+                                 unsigned long long clen,
+                                 const unsigned char *n,
+                                 const unsigned char *k)
+{
+    return crypto_secretbox_open_detached(m, c, mac, clen, n, k);
+}
+
+int
+crypto_box_open_detached(unsigned char *m, const unsigned char *c,
+                         const unsigned char *mac,
+                         unsigned long long clen, const unsigned char *n,
+                         const unsigned char *pk, const unsigned char *sk)
+{
+    unsigned char k[crypto_box_BEFORENMBYTES];
+    int           ret;
+
+    if (crypto_box_beforenm(k, pk, sk) != 0) {
+        return -1;
+    }
+    ret = crypto_box_open_detached_afternm(m, c, mac, clen, n, k);
+    sodium_memzero(k, sizeof k);
+
+    return ret;
+}
+
+int
+crypto_box_open_easy_afternm(unsigned char *m, const unsigned char *c,
+                             unsigned long long clen, const unsigned char *n,
+                             const unsigned char *k)
+{
+    if (clen < crypto_box_MACBYTES) {
+        return -1;
+    }
+    return crypto_box_open_detached_afternm(m, c + crypto_box_MACBYTES, c,
+                                            clen - crypto_box_MACBYTES,
+                                            n, k);
+}
+
+int
+crypto_box_open_easy(unsigned char *m, const unsigned char *c,
+                     unsigned long long clen, const unsigned char *n,
+                     const unsigned char *pk, const unsigned char *sk)
+{
+    if (clen < crypto_box_MACBYTES) {
+        return -1;
+    }
+    return crypto_box_open_detached(m, c + crypto_box_MACBYTES, c,
+                                    clen - crypto_box_MACBYTES,
+                                    n, pk, sk);
+}

+ 68 - 0
Sources/Sodium/crypto_box/crypto_box_seal.c

@@ -0,0 +1,68 @@
+
+#include <string.h>
+
+#include "crypto_box.h"
+#include "crypto_generichash.h"
+#include "private/common.h"
+#include "utils.h"
+
+static int
+_crypto_box_seal_nonce(unsigned char *nonce,
+                       const unsigned char *pk1, const unsigned char *pk2)
+{
+    crypto_generichash_state st;
+
+    crypto_generichash_init(&st, NULL, 0U, crypto_box_NONCEBYTES);
+    crypto_generichash_update(&st, pk1, crypto_box_PUBLICKEYBYTES);
+    crypto_generichash_update(&st, pk2, crypto_box_PUBLICKEYBYTES);
+    crypto_generichash_final(&st, nonce, crypto_box_NONCEBYTES);
+
+    return 0;
+}
+
+int
+crypto_box_seal(unsigned char *c, const unsigned char *m,
+                unsigned long long mlen, const unsigned char *pk)
+{
+    unsigned char nonce[crypto_box_NONCEBYTES];
+    unsigned char epk[crypto_box_PUBLICKEYBYTES];
+    unsigned char esk[crypto_box_SECRETKEYBYTES];
+    int           ret;
+
+    if (crypto_box_keypair(epk, esk) != 0) {
+        return -1; /* LCOV_EXCL_LINE */
+    }
+    memcpy(c, epk, crypto_box_PUBLICKEYBYTES);
+    _crypto_box_seal_nonce(nonce, epk, pk);
+    ret = crypto_box_easy(c + crypto_box_PUBLICKEYBYTES, m, mlen,
+                          nonce, pk, esk);
+    sodium_memzero(esk, sizeof esk);
+    sodium_memzero(epk, sizeof epk);
+    sodium_memzero(nonce, sizeof nonce);
+
+    return ret;
+}
+
+int
+crypto_box_seal_open(unsigned char *m, const unsigned char *c,
+                     unsigned long long clen,
+                     const unsigned char *pk, const unsigned char *sk)
+{
+    unsigned char nonce[crypto_box_NONCEBYTES];
+
+    if (clen < crypto_box_SEALBYTES) {
+        return -1;
+    }
+    _crypto_box_seal_nonce(nonce, c, pk);
+
+    COMPILER_ASSERT(crypto_box_PUBLICKEYBYTES < crypto_box_SEALBYTES);
+    return crypto_box_open_easy(m, c + crypto_box_PUBLICKEYBYTES,
+                                clen - crypto_box_PUBLICKEYBYTES,
+                                nonce, c, sk);
+}
+
+size_t
+crypto_box_sealbytes(void)
+{
+    return crypto_box_SEALBYTES;
+}

+ 204 - 0
Sources/Sodium/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c

@@ -0,0 +1,204 @@
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_box_curve25519xchacha20poly1305.h"
+#include "crypto_core_hchacha20.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_scalarmult_curve25519.h"
+#include "crypto_secretbox_xchacha20poly1305.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_box_curve25519xchacha20poly1305_seed_keypair(unsigned char *pk,
+                                                    unsigned char *sk,
+                                                    const unsigned char *seed)
+{
+    unsigned char hash[64];
+
+    crypto_hash_sha512(hash, seed, 32);
+    memcpy(sk, hash, 32);
+    sodium_memzero(hash, sizeof hash);
+
+    return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_keypair(unsigned char *pk,
+                                               unsigned char *sk)
+{
+    randombytes_buf(sk, 32);
+
+    return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_beforenm(unsigned char *k,
+                                                const unsigned char *pk,
+                                                const unsigned char *sk)
+{
+    static const unsigned char zero[16] = { 0 };
+    unsigned char s[32];
+
+    if (crypto_scalarmult_curve25519(s, sk, pk) != 0) {
+        return -1;
+    }
+    return crypto_core_hchacha20(k, zero, s, NULL);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_detached_afternm(
+    unsigned char *c, unsigned char *mac, const unsigned char *m,
+    unsigned long long mlen, const unsigned char *n, const unsigned char *k)
+{
+    return crypto_secretbox_xchacha20poly1305_detached(c, mac, m, mlen, n, k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_detached(
+    unsigned char *c, unsigned char *mac, const unsigned char *m,
+    unsigned long long mlen, const unsigned char *n, const unsigned char *pk,
+    const unsigned char *sk)
+{
+    unsigned char k[crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES];
+    int           ret;
+
+    COMPILER_ASSERT(crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES >=
+                    crypto_secretbox_xchacha20poly1305_KEYBYTES);
+    if (crypto_box_curve25519xchacha20poly1305_beforenm(k, pk, sk) != 0) {
+        return -1;
+    }
+    ret = crypto_box_curve25519xchacha20poly1305_detached_afternm(c, mac, m,
+                                                                  mlen, n, k);
+    sodium_memzero(k, sizeof k);
+
+    return ret;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_easy_afternm(unsigned char *c,
+                                                    const unsigned char *m,
+                                                    unsigned long long mlen,
+                                                    const unsigned char *n,
+                                                    const unsigned char *k)
+{
+    if (mlen > crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    return crypto_box_curve25519xchacha20poly1305_detached_afternm(
+        c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c, m, mlen, n, k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_easy(
+    unsigned char *c, const unsigned char *m, unsigned long long mlen,
+    const unsigned char *n, const unsigned char *pk, const unsigned char *sk)
+{
+    if (mlen > crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX) {
+        sodium_misuse();
+    }
+    return crypto_box_curve25519xchacha20poly1305_detached(
+        c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c, m, mlen, n, pk,
+        sk);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
+    unsigned char *m, const unsigned char *c, const unsigned char *mac,
+    unsigned long long clen, const unsigned char *n, const unsigned char *k)
+{
+    return crypto_secretbox_xchacha20poly1305_open_detached(m, c, mac, clen, n,
+                                                            k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_detached(
+    unsigned char *m, const unsigned char *c, const unsigned char *mac,
+    unsigned long long clen, const unsigned char *n, const unsigned char *pk,
+    const unsigned char *sk)
+{
+    unsigned char k[crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES];
+    int           ret;
+
+    if (crypto_box_curve25519xchacha20poly1305_beforenm(k, pk, sk) != 0) {
+        return -1;
+    }
+    ret = crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
+        m, c, mac, clen, n, k);
+    sodium_memzero(k, sizeof k);
+
+    return ret;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_easy_afternm(
+    unsigned char *m, const unsigned char *c, unsigned long long clen,
+    const unsigned char *n, const unsigned char *k)
+{
+    if (clen < crypto_box_curve25519xchacha20poly1305_MACBYTES) {
+        return -1;
+    }
+    return crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
+        m, c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c,
+        clen - crypto_box_curve25519xchacha20poly1305_MACBYTES, n, k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_easy(
+    unsigned char *m, const unsigned char *c, unsigned long long clen,
+    const unsigned char *n, const unsigned char *pk, const unsigned char *sk)
+{
+    if (clen < crypto_box_curve25519xchacha20poly1305_MACBYTES) {
+        return -1;
+    }
+    return crypto_box_curve25519xchacha20poly1305_open_detached(
+        m, c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c,
+        clen - crypto_box_curve25519xchacha20poly1305_MACBYTES, n, pk, sk);
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_seedbytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_SEEDBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_publickeybytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_secretkeybytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_beforenmbytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_noncebytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_NONCEBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_macbytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_MACBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_messagebytes_max(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX;
+}

+ 79 - 0
Sources/Sodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c

@@ -0,0 +1,79 @@
+
+#include <string.h>
+
+#include "crypto_box_curve25519xchacha20poly1305.h"
+#include "crypto_generichash.h"
+#include "private/common.h"
+#include "utils.h"
+
+static int
+_crypto_box_curve25519xchacha20poly1305_seal_nonce(unsigned char *nonce,
+                                                   const unsigned char *pk1,
+                                                   const unsigned char *pk2)
+{
+    crypto_generichash_state st;
+
+    crypto_generichash_init(&st, NULL, 0U,
+                            crypto_box_curve25519xchacha20poly1305_NONCEBYTES);
+    crypto_generichash_update(&st, pk1,
+                              crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES);
+    crypto_generichash_update(&st, pk2,
+                              crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES);
+    crypto_generichash_final(&st, nonce,
+                             crypto_box_curve25519xchacha20poly1305_NONCEBYTES);
+
+    return 0;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_seal(unsigned char *c, const unsigned char *m,
+                                            unsigned long long mlen,
+                                            const unsigned char *pk)
+{
+    unsigned char nonce[crypto_box_curve25519xchacha20poly1305_NONCEBYTES];
+    unsigned char epk[crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES];
+    unsigned char esk[crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES];
+    int           ret;
+
+    if (crypto_box_curve25519xchacha20poly1305_keypair(epk, esk) != 0) {
+        return -1; /* LCOV_EXCL_LINE */
+    }
+    memcpy(c, epk, crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES);
+    _crypto_box_curve25519xchacha20poly1305_seal_nonce(nonce, epk, pk);
+    ret = crypto_box_curve25519xchacha20poly1305_easy(
+         c + crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES, m, mlen,
+         nonce, pk, esk);
+    sodium_memzero(esk, sizeof esk);
+    sodium_memzero(epk, sizeof epk);
+    sodium_memzero(nonce, sizeof nonce);
+
+    return ret;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_seal_open(unsigned char *m, const unsigned char *c,
+                                                 unsigned long long clen,
+                                                 const unsigned char *pk,
+                                                 const unsigned char *sk)
+{
+    unsigned char nonce[crypto_box_curve25519xchacha20poly1305_NONCEBYTES];
+
+    if (clen < crypto_box_curve25519xchacha20poly1305_SEALBYTES) {
+        return -1;
+    }
+    _crypto_box_curve25519xchacha20poly1305_seal_nonce(nonce, c, pk);
+
+    COMPILER_ASSERT(crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES <
+                    crypto_box_curve25519xchacha20poly1305_SEALBYTES);
+
+    return crypto_box_curve25519xchacha20poly1305_open_easy(
+         m, c + crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES,
+         clen - crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES,
+         nonce, c, sk);
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_sealbytes(void)
+{
+    return crypto_box_curve25519xchacha20poly1305_SEALBYTES;
+}

+ 156 - 0
Sources/Sodium/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c

@@ -0,0 +1,156 @@
+#include <string.h>
+
+#include "crypto_box_curve25519xsalsa20poly1305.h"
+#include "crypto_core_hsalsa20.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_scalarmult_curve25519.h"
+#include "crypto_secretbox_xsalsa20poly1305.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_box_curve25519xsalsa20poly1305_seed_keypair(unsigned char *pk,
+                                                   unsigned char *sk,
+                                                   const unsigned char *seed)
+{
+    unsigned char hash[64];
+
+    crypto_hash_sha512(hash, seed, 32);
+    memcpy(sk, hash, 32);
+    sodium_memzero(hash, sizeof hash);
+
+    return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_keypair(unsigned char *pk,
+                                              unsigned char *sk)
+{
+    randombytes_buf(sk, 32);
+
+    return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_beforenm(unsigned char *k,
+                                               const unsigned char *pk,
+                                               const unsigned char *sk)
+{
+    static const unsigned char zero[16] = { 0 };
+    unsigned char s[32];
+
+    if (crypto_scalarmult_curve25519(s, sk, pk) != 0) {
+        return -1;
+    }
+    return crypto_core_hsalsa20(k, zero, s, NULL);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_afternm(unsigned char *c,
+                                              const unsigned char *m,
+                                              unsigned long long mlen,
+                                              const unsigned char *n,
+                                              const unsigned char *k)
+{
+    return crypto_secretbox_xsalsa20poly1305(c, m, mlen, n, k);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_open_afternm(unsigned char *m,
+                                                   const unsigned char *c,
+                                                   unsigned long long clen,
+                                                   const unsigned char *n,
+                                                   const unsigned char *k)
+{
+    return crypto_secretbox_xsalsa20poly1305_open(m, c, clen, n, k);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305(unsigned char *c, const unsigned char *m,
+                                      unsigned long long   mlen,
+                                      const unsigned char *n,
+                                      const unsigned char *pk,
+                                      const unsigned char *sk)
+{
+    unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
+    int           ret;
+
+    if (crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk) != 0) {
+        return -1;
+    }
+    ret = crypto_box_curve25519xsalsa20poly1305_afternm(c, m, mlen, n, k);
+    sodium_memzero(k, sizeof k);
+
+    return ret;
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_open(
+    unsigned char *m, const unsigned char *c, unsigned long long clen,
+    const unsigned char *n, const unsigned char *pk, const unsigned char *sk)
+{
+    unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
+    int           ret;
+
+    if (crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk) != 0) {
+        return -1;
+    }
+    ret = crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k);
+    sodium_memzero(k, sizeof k);
+
+    return ret;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_seedbytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_SEEDBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_publickeybytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_secretkeybytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_beforenmbytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_noncebytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_NONCEBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_zerobytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_ZEROBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_boxzerobytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_macbytes(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_MACBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_messagebytes_max(void)
+{
+    return crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX;
+}

+ 225 - 0
Sources/Sodium/crypto_core/ed25519/core_ed25519.c

@@ -0,0 +1,225 @@
+
+#include <stdint.h>
+
+#include "crypto_core_ed25519.h"
+#include "private/common.h"
+#include "private/ed25519_ref10.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_core_ed25519_is_valid_point(const unsigned char *p)
+{
+    ge25519_p3 p_p3;
+
+    if (ge25519_is_canonical(p) == 0 ||
+        ge25519_has_small_order(p) != 0 ||
+        ge25519_frombytes(&p_p3, p) != 0 ||
+        ge25519_is_on_curve(&p_p3) == 0 ||
+        ge25519_is_on_main_subgroup(&p_p3) == 0) {
+        return 0;
+    }
+    return 1;
+}
+
+int
+crypto_core_ed25519_add(unsigned char *r,
+                        const unsigned char *p, const unsigned char *q)
+{
+    ge25519_p3     p_p3, q_p3, r_p3;
+    ge25519_p1p1   r_p1p1;
+    ge25519_cached q_cached;
+
+    if (ge25519_frombytes(&p_p3, p) != 0 || ge25519_is_on_curve(&p_p3) == 0 ||
+        ge25519_frombytes(&q_p3, q) != 0 || ge25519_is_on_curve(&q_p3) == 0) {
+        return -1;
+    }
+    ge25519_p3_to_cached(&q_cached, &q_p3);
+    ge25519_add(&r_p1p1, &p_p3, &q_cached);
+    ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+    ge25519_p3_tobytes(r, &r_p3);
+
+    return 0;
+}
+
+int
+crypto_core_ed25519_sub(unsigned char *r,
+                        const unsigned char *p, const unsigned char *q)
+{
+    ge25519_p3     p_p3, q_p3, r_p3;
+    ge25519_p1p1   r_p1p1;
+    ge25519_cached q_cached;
+
+    if (ge25519_frombytes(&p_p3, p) != 0 || ge25519_is_on_curve(&p_p3) == 0 ||
+        ge25519_frombytes(&q_p3, q) != 0 || ge25519_is_on_curve(&q_p3) == 0) {
+        return -1;
+    }
+    ge25519_p3_to_cached(&q_cached, &q_p3);
+    ge25519_sub(&r_p1p1, &p_p3, &q_cached);
+    ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+    ge25519_p3_tobytes(r, &r_p3);
+
+    return 0;
+}
+
+int
+crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r)
+{
+    ge25519_from_uniform(p, r);
+
+    return 0;
+}
+
+int
+crypto_core_ed25519_from_hash(unsigned char *p, const unsigned char *h)
+{
+    ge25519_from_hash(p, h);
+
+    return 0;
+}
+
+void
+crypto_core_ed25519_random(unsigned char *p)
+{
+    unsigned char h[crypto_core_ed25519_HASHBYTES];
+
+    randombytes_buf(h, sizeof h);
+    (void) crypto_core_ed25519_from_hash(p, h);
+}
+
+void
+crypto_core_ed25519_scalar_random(unsigned char *r)
+{
+    do {
+        randombytes_buf(r, crypto_core_ed25519_SCALARBYTES);
+        r[crypto_core_ed25519_SCALARBYTES - 1] &= 0x1f;
+    } while (sc25519_is_canonical(r) == 0 ||
+             sodium_is_zero(r, crypto_core_ed25519_SCALARBYTES));
+}
+
+int
+crypto_core_ed25519_scalar_invert(unsigned char *recip, const unsigned char *s)
+{
+    sc25519_invert(recip, s);
+
+    return - sodium_is_zero(s, crypto_core_ed25519_SCALARBYTES);
+}
+
+/* 2^252+27742317777372353535851937790883648493 */
+static const unsigned char L[] = {
+    0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
+    0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
+};
+
+void
+crypto_core_ed25519_scalar_negate(unsigned char *neg, const unsigned char *s)
+{
+    unsigned char t_[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+    unsigned char s_[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+
+    COMPILER_ASSERT(crypto_core_ed25519_NONREDUCEDSCALARBYTES >=
+                    2 * crypto_core_ed25519_SCALARBYTES);
+    memset(t_, 0, sizeof t_);
+    memset(s_, 0, sizeof s_);
+    memcpy(t_ + crypto_core_ed25519_SCALARBYTES, L,
+           crypto_core_ed25519_SCALARBYTES);
+    memcpy(s_, s, crypto_core_ed25519_SCALARBYTES);
+    sodium_sub(t_, s_, sizeof t_);
+    sc25519_reduce(t_);
+    memcpy(neg, t_, crypto_core_ed25519_SCALARBYTES);
+}
+
+void
+crypto_core_ed25519_scalar_complement(unsigned char *comp,
+                                      const unsigned char *s)
+{
+    unsigned char t_[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+    unsigned char s_[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+
+    COMPILER_ASSERT(crypto_core_ed25519_NONREDUCEDSCALARBYTES >=
+                    2 * crypto_core_ed25519_SCALARBYTES);
+    memset(t_, 0, sizeof t_);
+    memset(s_, 0, sizeof s_);
+    t_[0]++;
+    memcpy(t_ + crypto_core_ed25519_SCALARBYTES, L,
+           crypto_core_ed25519_SCALARBYTES);
+    memcpy(s_, s, crypto_core_ed25519_SCALARBYTES);
+    sodium_sub(t_, s_, sizeof t_);
+    sc25519_reduce(t_);
+    memcpy(comp, t_, crypto_core_ed25519_SCALARBYTES);
+}
+
+void
+crypto_core_ed25519_scalar_add(unsigned char *z, const unsigned char *x,
+                               const unsigned char *y)
+{
+    unsigned char x_[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+    unsigned char y_[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+
+    memset(x_, 0, sizeof x_);
+    memset(y_, 0, sizeof y_);
+    memcpy(x_, x, crypto_core_ed25519_SCALARBYTES);
+    memcpy(y_, y, crypto_core_ed25519_SCALARBYTES);
+    sodium_add(x_, y_, crypto_core_ed25519_SCALARBYTES);
+    crypto_core_ed25519_scalar_reduce(z, x_);
+}
+
+void
+crypto_core_ed25519_scalar_sub(unsigned char *z, const unsigned char *x,
+                               const unsigned char *y)
+{
+    unsigned char yn[crypto_core_ed25519_SCALARBYTES];
+
+    crypto_core_ed25519_scalar_negate(yn, y);
+    crypto_core_ed25519_scalar_add(z, x, yn);
+}
+
+void
+crypto_core_ed25519_scalar_mul(unsigned char *z, const unsigned char *x,
+                               const unsigned char *y)
+{
+    sc25519_mul(z, x, y);
+}
+
+void
+crypto_core_ed25519_scalar_reduce(unsigned char *r,
+                                  const unsigned char *s)
+{
+    unsigned char t[crypto_core_ed25519_NONREDUCEDSCALARBYTES];
+
+    memcpy(t, s, sizeof t);
+    sc25519_reduce(t);
+    memcpy(r, t, crypto_core_ed25519_SCALARBYTES);
+    sodium_memzero(t, sizeof t);
+}
+
+size_t
+crypto_core_ed25519_bytes(void)
+{
+    return crypto_core_ed25519_BYTES;
+}
+
+size_t
+crypto_core_ed25519_nonreducedscalarbytes(void)
+{
+    return crypto_core_ed25519_NONREDUCEDSCALARBYTES;
+}
+
+size_t
+crypto_core_ed25519_uniformbytes(void)
+{
+    return crypto_core_ed25519_UNIFORMBYTES;
+}
+
+size_t
+crypto_core_ed25519_hashbytes(void)
+{
+    return crypto_core_ed25519_HASHBYTES;
+}
+
+size_t
+crypto_core_ed25519_scalarbytes(void)
+{
+    return crypto_core_ed25519_SCALARBYTES;
+}

+ 156 - 0
Sources/Sodium/crypto_core/ed25519/core_ristretto255.c

@@ -0,0 +1,156 @@
+
+#include <stdint.h>
+
+#include "crypto_core_ed25519.h"
+#include "crypto_core_ristretto255.h"
+#include "private/common.h"
+#include "private/ed25519_ref10.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_core_ristretto255_is_valid_point(const unsigned char *p)
+{
+    ge25519_p3 p_p3;
+
+    if (ristretto255_frombytes(&p_p3, p) != 0) {
+        return 0;
+    }
+    return 1;
+}
+
+int
+crypto_core_ristretto255_add(unsigned char *r,
+                             const unsigned char *p, const unsigned char *q)
+{
+    ge25519_p3     p_p3, q_p3, r_p3;
+    ge25519_p1p1   r_p1p1;
+    ge25519_cached q_cached;
+
+    if (ristretto255_frombytes(&p_p3, p) != 0 ||
+        ristretto255_frombytes(&q_p3, q) != 0) {
+        return -1;
+    }
+    ge25519_p3_to_cached(&q_cached, &q_p3);
+    ge25519_add(&r_p1p1, &p_p3, &q_cached);
+    ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+    ristretto255_p3_tobytes(r, &r_p3);
+
+    return 0;
+}
+
+int
+crypto_core_ristretto255_sub(unsigned char *r,
+                             const unsigned char *p, const unsigned char *q)
+{
+    ge25519_p3     p_p3, q_p3, r_p3;
+    ge25519_p1p1   r_p1p1;
+    ge25519_cached q_cached;
+
+    if (ristretto255_frombytes(&p_p3, p) != 0 ||
+        ristretto255_frombytes(&q_p3, q) != 0) {
+        return -1;
+    }
+    ge25519_p3_to_cached(&q_cached, &q_p3);
+    ge25519_sub(&r_p1p1, &p_p3, &q_cached);
+    ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+    ristretto255_p3_tobytes(r, &r_p3);
+
+    return 0;
+}
+
+int
+crypto_core_ristretto255_from_hash(unsigned char *p, const unsigned char *r)
+{
+    ristretto255_from_hash(p, r);
+
+    return 0;
+}
+
+void
+crypto_core_ristretto255_random(unsigned char *p)
+{
+    unsigned char h[crypto_core_ristretto255_HASHBYTES];
+
+    randombytes_buf(h, sizeof h);
+    (void) crypto_core_ristretto255_from_hash(p, h);
+}
+
+void
+crypto_core_ristretto255_scalar_random(unsigned char *r)
+{
+    crypto_core_ed25519_scalar_random(r);
+}
+
+int
+crypto_core_ristretto255_scalar_invert(unsigned char *recip,
+                                       const unsigned char *s)
+{
+    return crypto_core_ed25519_scalar_invert(recip, s);
+}
+
+void
+crypto_core_ristretto255_scalar_negate(unsigned char *neg,
+                                       const unsigned char *s)
+{
+    crypto_core_ed25519_scalar_negate(neg, s);
+}
+
+void
+crypto_core_ristretto255_scalar_complement(unsigned char *comp,
+                                           const unsigned char *s)
+{
+    crypto_core_ed25519_scalar_complement(comp, s);
+}
+
+void
+crypto_core_ristretto255_scalar_add(unsigned char *z, const unsigned char *x,
+                                    const unsigned char *y)
+{
+    crypto_core_ed25519_scalar_add(z, x, y);
+}
+
+void
+crypto_core_ristretto255_scalar_sub(unsigned char *z, const unsigned char *x,
+                                    const unsigned char *y)
+{
+    crypto_core_ed25519_scalar_sub(z, x, y);
+}
+
+void
+crypto_core_ristretto255_scalar_mul(unsigned char *z, const unsigned char *x,
+                                    const unsigned char *y)
+{
+    sc25519_mul(z, x, y);
+}
+
+void
+crypto_core_ristretto255_scalar_reduce(unsigned char *r,
+                                       const unsigned char *s)
+{
+    crypto_core_ed25519_scalar_reduce(r, s);
+}
+
+size_t
+crypto_core_ristretto255_bytes(void)
+{
+    return crypto_core_ristretto255_BYTES;
+}
+
+size_t
+crypto_core_ristretto255_nonreducedscalarbytes(void)
+{
+    return crypto_core_ristretto255_NONREDUCEDSCALARBYTES;
+}
+
+size_t
+crypto_core_ristretto255_hashbytes(void)
+{
+    return crypto_core_ristretto255_HASHBYTES;
+}
+
+size_t
+crypto_core_ristretto255_scalarbytes(void)
+{
+    return crypto_core_ristretto255_SCALARBYTES;
+}

+ 2866 - 0
Sources/Sodium/crypto_core/ed25519/ref10/ed25519_ref10.c

@@ -0,0 +1,2866 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_verify_32.h"
+#include "private/common.h"
+#include "private/ed25519_ref10.h"
+#include "utils.h"
+
+static inline uint64_t
+load_3(const unsigned char *in)
+{
+    uint64_t result;
+
+    result = (uint64_t) in[0];
+    result |= ((uint64_t) in[1]) << 8;
+    result |= ((uint64_t) in[2]) << 16;
+
+    return result;
+}
+
+static inline uint64_t
+load_4(const unsigned char *in)
+{
+    uint64_t result;
+
+    result = (uint64_t) in[0];
+    result |= ((uint64_t) in[1]) << 8;
+    result |= ((uint64_t) in[2]) << 16;
+    result |= ((uint64_t) in[3]) << 24;
+
+    return result;
+}
+
+/*
+ * Field arithmetic:
+ * Use 5*51 bit limbs on 64-bit systems with support for 128 bit arithmetic,
+ * and 10*25.5 bit limbs elsewhere.
+ *
+ * Functions used elsewhere that are candidates for inlining are defined
+ * via "private/curve25519_ref10.h".
+ */
+
+#ifdef HAVE_TI_MODE
+# include "fe_51/constants.h"
+# include "fe_51/fe.h"
+#else
+# include "fe_25_5/constants.h"
+# include "fe_25_5/fe.h"
+#endif
+
+void
+fe25519_invert(fe25519 out, const fe25519 z)
+{
+    fe25519 t0;
+    fe25519 t1;
+    fe25519 t2;
+    fe25519 t3;
+    int     i;
+
+    fe25519_sq(t0, z);
+    fe25519_sq(t1, t0);
+    fe25519_sq(t1, t1);
+    fe25519_mul(t1, z, t1);
+    fe25519_mul(t0, t0, t1);
+    fe25519_sq(t2, t0);
+    fe25519_mul(t1, t1, t2);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 5; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 10; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t2, t2, t1);
+    fe25519_sq(t3, t2);
+    for (i = 1; i < 20; ++i) {
+        fe25519_sq(t3, t3);
+    }
+    fe25519_mul(t2, t3, t2);
+    fe25519_sq(t2, t2);
+    for (i = 1; i < 10; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 50; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t2, t2, t1);
+    fe25519_sq(t3, t2);
+    for (i = 1; i < 100; ++i) {
+        fe25519_sq(t3, t3);
+    }
+    fe25519_mul(t2, t3, t2);
+    fe25519_sq(t2, t2);
+    for (i = 1; i < 50; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1);
+    for (i = 1; i < 5; ++i) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(out, t1, t0);
+}
+
+static void
+fe25519_pow22523(fe25519 out, const fe25519 z)
+{
+    fe25519 t0;
+    fe25519 t1;
+    fe25519 t2;
+    int     i;
+
+    fe25519_sq(t0, z);
+    fe25519_sq(t1, t0);
+    fe25519_sq(t1, t1);
+    fe25519_mul(t1, z, t1);
+    fe25519_mul(t0, t0, t1);
+    fe25519_sq(t0, t0);
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t1, t0);
+    for (i = 1; i < 5; ++i) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t1, t0);
+    for (i = 1; i < 10; ++i) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(t1, t1, t0);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 20; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1);
+    for (i = 1; i < 10; ++i) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t1, t0);
+    for (i = 1; i < 50; ++i) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(t1, t1, t0);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 100; ++i) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1);
+    for (i = 1; i < 50; ++i) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t0, t0);
+    fe25519_sq(t0, t0);
+    fe25519_mul(out, t0, z);
+}
+
+static inline void
+fe25519_cneg(fe25519 h, const fe25519 f, unsigned int b)
+{
+    fe25519 negf;
+
+    fe25519_neg(negf, f);
+    fe25519_copy(h, f);
+    fe25519_cmov(h, negf, b);
+}
+
+static inline void
+fe25519_abs(fe25519 h, const fe25519 f)
+{
+    fe25519_cneg(h, f, fe25519_isnegative(f));
+}
+
+/*
+ r = p + q
+ */
+
+void
+ge25519_add(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q)
+{
+    fe25519 t0;
+
+    fe25519_add(r->X, p->Y, p->X);
+    fe25519_sub(r->Y, p->Y, p->X);
+    fe25519_mul(r->Z, r->X, q->YplusX);
+    fe25519_mul(r->Y, r->Y, q->YminusX);
+    fe25519_mul(r->T, q->T2d, p->T);
+    fe25519_mul(r->X, p->Z, q->Z);
+    fe25519_add(t0, r->X, r->X);
+    fe25519_sub(r->X, r->Z, r->Y);
+    fe25519_add(r->Y, r->Z, r->Y);
+    fe25519_add(r->Z, t0, r->T);
+    fe25519_sub(r->T, t0, r->T);
+}
+
+static void
+slide_vartime(signed char *r, const unsigned char *a)
+{
+    int i;
+    int b;
+    int k;
+    int ribs;
+    int cmp;
+
+    for (i = 0; i < 256; ++i) {
+        r[i] = 1 & (a[i >> 3] >> (i & 7));
+    }
+    for (i = 0; i < 256; ++i) {
+        if (! r[i]) {
+            continue;
+        }
+        for (b = 1; b <= 6 && i + b < 256; ++b) {
+            if (! r[i + b]) {
+                continue;
+            }
+            ribs = r[i + b] << b;
+            cmp = r[i] + ribs;
+            if (cmp <= 15) {
+                r[i] = cmp;
+                r[i + b] = 0;
+            } else {
+                cmp = r[i] - ribs;
+                if (cmp < -15) {
+                    break;
+                }
+                r[i] = cmp;
+                for (k = i + b; k < 256; ++k) {
+                    if (! r[k]) {
+                        r[k] = 1;
+                        break;
+                    }
+                    r[k] = 0;
+                }
+            }
+        }
+    }
+}
+
+int
+ge25519_frombytes(ge25519_p3 *h, const unsigned char *s)
+{
+    fe25519 u;
+    fe25519 v;
+    fe25519 v3;
+    fe25519 vxx;
+    fe25519 m_root_check, p_root_check;
+    fe25519 negx;
+    fe25519 x_sqrtm1;
+    int     has_m_root, has_p_root;
+
+    fe25519_frombytes(h->Y, s);
+    fe25519_1(h->Z);
+    fe25519_sq(u, h->Y);
+    fe25519_mul(v, u, d);
+    fe25519_sub(u, u, h->Z); /* u = y^2-1 */
+    fe25519_add(v, v, h->Z); /* v = dy^2+1 */
+
+    fe25519_sq(v3, v);
+    fe25519_mul(v3, v3, v); /* v3 = v^3 */
+    fe25519_sq(h->X, v3);
+    fe25519_mul(h->X, h->X, v);
+    fe25519_mul(h->X, h->X, u); /* x = uv^7 */
+
+    fe25519_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
+    fe25519_mul(h->X, h->X, v3);
+    fe25519_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+    fe25519_sq(vxx, h->X);
+    fe25519_mul(vxx, vxx, v);
+    fe25519_sub(m_root_check, vxx, u); /* vx^2-u */
+    fe25519_add(p_root_check, vxx, u); /* vx^2+u */
+    has_m_root = fe25519_iszero(m_root_check);
+    has_p_root = fe25519_iszero(p_root_check);
+    fe25519_mul(x_sqrtm1, h->X, sqrtm1); /* x*sqrt(-1) */
+    fe25519_cmov(h->X, x_sqrtm1, 1 - has_m_root);
+
+    fe25519_neg(negx, h->X);
+    fe25519_cmov(h->X, negx, fe25519_isnegative(h->X) ^ (s[31] >> 7));
+    fe25519_mul(h->T, h->X, h->Y);
+
+    return (has_m_root | has_p_root) - 1;
+}
+
+int
+ge25519_frombytes_negate_vartime(ge25519_p3 *h, const unsigned char *s)
+{
+    fe25519 u;
+    fe25519 v;
+    fe25519 v3;
+    fe25519 vxx;
+    fe25519 m_root_check, p_root_check;
+
+    fe25519_frombytes(h->Y, s);
+    fe25519_1(h->Z);
+    fe25519_sq(u, h->Y);
+    fe25519_mul(v, u, d);
+    fe25519_sub(u, u, h->Z); /* u = y^2-1 */
+    fe25519_add(v, v, h->Z); /* v = dy^2+1 */
+
+    fe25519_sq(v3, v);
+    fe25519_mul(v3, v3, v); /* v3 = v^3 */
+    fe25519_sq(h->X, v3);
+    fe25519_mul(h->X, h->X, v);
+    fe25519_mul(h->X, h->X, u); /* x = uv^7 */
+
+    fe25519_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
+    fe25519_mul(h->X, h->X, v3);
+    fe25519_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+    fe25519_sq(vxx, h->X);
+    fe25519_mul(vxx, vxx, v);
+    fe25519_sub(m_root_check, vxx, u); /* vx^2-u */
+    if (fe25519_iszero(m_root_check) == 0) {
+        fe25519_add(p_root_check, vxx, u); /* vx^2+u */
+        if (fe25519_iszero(p_root_check) == 0) {
+            return -1;
+        }
+        fe25519_mul(h->X, h->X, sqrtm1);
+    }
+
+    if (fe25519_isnegative(h->X) == (s[31] >> 7)) {
+        fe25519_neg(h->X, h->X);
+    }
+    fe25519_mul(h->T, h->X, h->Y);
+
+    return 0;
+}
+
+/*
+ r = p + q
+ */
+
+static void
+ge25519_madd(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_precomp *q)
+{
+    fe25519 t0;
+
+    fe25519_add(r->X, p->Y, p->X);
+    fe25519_sub(r->Y, p->Y, p->X);
+    fe25519_mul(r->Z, r->X, q->yplusx);
+    fe25519_mul(r->Y, r->Y, q->yminusx);
+    fe25519_mul(r->T, q->xy2d, p->T);
+    fe25519_add(t0, p->Z, p->Z);
+    fe25519_sub(r->X, r->Z, r->Y);
+    fe25519_add(r->Y, r->Z, r->Y);
+    fe25519_add(r->Z, t0, r->T);
+    fe25519_sub(r->T, t0, r->T);
+}
+
+/*
+ r = p - q
+ */
+
+static void
+ge25519_msub(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_precomp *q)
+{
+    fe25519 t0;
+
+    fe25519_add(r->X, p->Y, p->X);
+    fe25519_sub(r->Y, p->Y, p->X);
+    fe25519_mul(r->Z, r->X, q->yminusx);
+    fe25519_mul(r->Y, r->Y, q->yplusx);
+    fe25519_mul(r->T, q->xy2d, p->T);
+    fe25519_add(t0, p->Z, p->Z);
+    fe25519_sub(r->X, r->Z, r->Y);
+    fe25519_add(r->Y, r->Z, r->Y);
+    fe25519_sub(r->Z, t0, r->T);
+    fe25519_add(r->T, t0, r->T);
+}
+
+/*
+ r = p
+ */
+
+void
+ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p)
+{
+    fe25519_mul(r->X, p->X, p->T);
+    fe25519_mul(r->Y, p->Y, p->Z);
+    fe25519_mul(r->Z, p->Z, p->T);
+}
+
+/*
+ r = p
+ */
+
+void
+ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p)
+{
+    fe25519_mul(r->X, p->X, p->T);
+    fe25519_mul(r->Y, p->Y, p->Z);
+    fe25519_mul(r->Z, p->Z, p->T);
+    fe25519_mul(r->T, p->X, p->Y);
+}
+
+static void
+ge25519_p2_0(ge25519_p2 *h)
+{
+    fe25519_0(h->X);
+    fe25519_1(h->Y);
+    fe25519_1(h->Z);
+}
+
+/*
+ r = 2 * p
+ */
+
+static void
+ge25519_p2_dbl(ge25519_p1p1 *r, const ge25519_p2 *p)
+{
+    fe25519 t0;
+
+    fe25519_sq(r->X, p->X);
+    fe25519_sq(r->Z, p->Y);
+    fe25519_sq2(r->T, p->Z);
+    fe25519_add(r->Y, p->X, p->Y);
+    fe25519_sq(t0, r->Y);
+    fe25519_add(r->Y, r->Z, r->X);
+    fe25519_sub(r->Z, r->Z, r->X);
+    fe25519_sub(r->X, t0, r->Y);
+    fe25519_sub(r->T, r->T, r->Z);
+}
+
+static void
+ge25519_p3_0(ge25519_p3 *h)
+{
+    fe25519_0(h->X);
+    fe25519_1(h->Y);
+    fe25519_1(h->Z);
+    fe25519_0(h->T);
+}
+
+static void
+ge25519_cached_0(ge25519_cached *h)
+{
+    fe25519_1(h->YplusX);
+    fe25519_1(h->YminusX);
+    fe25519_1(h->Z);
+    fe25519_0(h->T2d);
+}
+
+/*
+ r = p
+ */
+
+void
+ge25519_p3_to_cached(ge25519_cached *r, const ge25519_p3 *p)
+{
+    fe25519_add(r->YplusX, p->Y, p->X);
+    fe25519_sub(r->YminusX, p->Y, p->X);
+    fe25519_copy(r->Z, p->Z);
+    fe25519_mul(r->T2d, p->T, d2);
+}
+
+static void
+ge25519_p3_to_precomp(ge25519_precomp *pi, const ge25519_p3 *p)
+{
+    fe25519 recip;
+    fe25519 x;
+    fe25519 y;
+    fe25519 xy;
+
+    fe25519_invert(recip, p->Z);
+    fe25519_mul(x, p->X, recip);
+    fe25519_mul(y, p->Y, recip);
+    fe25519_add(pi->yplusx, y, x);
+    fe25519_sub(pi->yminusx, y, x);
+    fe25519_mul(xy, x, y);
+    fe25519_mul(pi->xy2d, xy, d2);
+}
+
+/*
+ r = p
+ */
+
+static void
+ge25519_p3_to_p2(ge25519_p2 *r, const ge25519_p3 *p)
+{
+    fe25519_copy(r->X, p->X);
+    fe25519_copy(r->Y, p->Y);
+    fe25519_copy(r->Z, p->Z);
+}
+
+void
+ge25519_p3_tobytes(unsigned char *s, const ge25519_p3 *h)
+{
+    fe25519 recip;
+    fe25519 x;
+    fe25519 y;
+
+    fe25519_invert(recip, h->Z);
+    fe25519_mul(x, h->X, recip);
+    fe25519_mul(y, h->Y, recip);
+    fe25519_tobytes(s, y);
+    s[31] ^= fe25519_isnegative(x) << 7;
+}
+
+/*
+ r = 2 * p
+ */
+
+static void
+ge25519_p3_dbl(ge25519_p1p1 *r, const ge25519_p3 *p)
+{
+    ge25519_p2 q;
+    ge25519_p3_to_p2(&q, p);
+    ge25519_p2_dbl(r, &q);
+}
+
+static void
+ge25519_precomp_0(ge25519_precomp *h)
+{
+    fe25519_1(h->yplusx);
+    fe25519_1(h->yminusx);
+    fe25519_0(h->xy2d);
+}
+
+static unsigned char
+equal(signed char b, signed char c)
+{
+    unsigned char ub = b;
+    unsigned char uc = c;
+    unsigned char x  = ub ^ uc; /* 0: yes; 1..255: no */
+    uint32_t      y  = (uint32_t) x; /* 0: yes; 1..255: no */
+
+    y -= 1;   /* 4294967295: yes; 0..254: no */
+    y >>= 31; /* 1: yes; 0: no */
+
+    return y;
+}
+
+static unsigned char
+negative(signed char b)
+{
+    /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
+    uint64_t x = b;
+
+    x >>= 63; /* 1: yes; 0: no */
+
+    return x;
+}
+
+static void
+ge25519_cmov(ge25519_precomp *t, const ge25519_precomp *u, unsigned char b)
+{
+    fe25519_cmov(t->yplusx, u->yplusx, b);
+    fe25519_cmov(t->yminusx, u->yminusx, b);
+    fe25519_cmov(t->xy2d, u->xy2d, b);
+}
+
+static void
+ge25519_cmov_cached(ge25519_cached *t, const ge25519_cached *u, unsigned char b)
+{
+    fe25519_cmov(t->YplusX, u->YplusX, b);
+    fe25519_cmov(t->YminusX, u->YminusX, b);
+    fe25519_cmov(t->Z, u->Z, b);
+    fe25519_cmov(t->T2d, u->T2d, b);
+}
+
+static void
+ge25519_cmov8(ge25519_precomp *t, const ge25519_precomp precomp[8], const signed char b)
+{
+    ge25519_precomp     minust;
+    const unsigned char bnegative = negative(b);
+    const unsigned char babs      = b - (((-bnegative) & b) * ((signed char) 1 << 1));
+
+    ge25519_precomp_0(t);
+    ge25519_cmov(t, &precomp[0], equal(babs, 1));
+    ge25519_cmov(t, &precomp[1], equal(babs, 2));
+    ge25519_cmov(t, &precomp[2], equal(babs, 3));
+    ge25519_cmov(t, &precomp[3], equal(babs, 4));
+    ge25519_cmov(t, &precomp[4], equal(babs, 5));
+    ge25519_cmov(t, &precomp[5], equal(babs, 6));
+    ge25519_cmov(t, &precomp[6], equal(babs, 7));
+    ge25519_cmov(t, &precomp[7], equal(babs, 8));
+    fe25519_copy(minust.yplusx, t->yminusx);
+    fe25519_copy(minust.yminusx, t->yplusx);
+    fe25519_neg(minust.xy2d, t->xy2d);
+    ge25519_cmov(t, &minust, bnegative);
+}
+
+static void
+ge25519_cmov8_base(ge25519_precomp *t, const int pos, const signed char b)
+{
+    static const ge25519_precomp base[32][8] = { /* base[i][j] = (j+1)*256^i*B */
+#ifdef HAVE_TI_MODE
+# include "fe_51/base.h"
+#else
+# include "fe_25_5/base.h"
+#endif
+    };
+    ge25519_cmov8(t, base[pos], b);
+}
+
+static void
+ge25519_cmov8_cached(ge25519_cached *t, const ge25519_cached cached[8], const signed char b)
+{
+    ge25519_cached      minust;
+    const unsigned char bnegative = negative(b);
+    const unsigned char babs      = b - (((-bnegative) & b) * ((signed char) 1 << 1));
+
+    ge25519_cached_0(t);
+    ge25519_cmov_cached(t, &cached[0], equal(babs, 1));
+    ge25519_cmov_cached(t, &cached[1], equal(babs, 2));
+    ge25519_cmov_cached(t, &cached[2], equal(babs, 3));
+    ge25519_cmov_cached(t, &cached[3], equal(babs, 4));
+    ge25519_cmov_cached(t, &cached[4], equal(babs, 5));
+    ge25519_cmov_cached(t, &cached[5], equal(babs, 6));
+    ge25519_cmov_cached(t, &cached[6], equal(babs, 7));
+    ge25519_cmov_cached(t, &cached[7], equal(babs, 8));
+    fe25519_copy(minust.YplusX, t->YminusX);
+    fe25519_copy(minust.YminusX, t->YplusX);
+    fe25519_copy(minust.Z, t->Z);
+    fe25519_neg(minust.T2d, t->T2d);
+    ge25519_cmov_cached(t, &minust, bnegative);
+}
+
+/*
+ r = p - q
+ */
+
+void
+ge25519_sub(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q)
+{
+    fe25519 t0;
+
+    fe25519_add(r->X, p->Y, p->X);
+    fe25519_sub(r->Y, p->Y, p->X);
+    fe25519_mul(r->Z, r->X, q->YminusX);
+    fe25519_mul(r->Y, r->Y, q->YplusX);
+    fe25519_mul(r->T, q->T2d, p->T);
+    fe25519_mul(r->X, p->Z, q->Z);
+    fe25519_add(t0, r->X, r->X);
+    fe25519_sub(r->X, r->Z, r->Y);
+    fe25519_add(r->Y, r->Z, r->Y);
+    fe25519_sub(r->Z, t0, r->T);
+    fe25519_add(r->T, t0, r->T);
+}
+
+void
+ge25519_tobytes(unsigned char *s, const ge25519_p2 *h)
+{
+    fe25519 recip;
+    fe25519 x;
+    fe25519 y;
+
+    fe25519_invert(recip, h->Z);
+    fe25519_mul(x, h->X, recip);
+    fe25519_mul(y, h->Y, recip);
+    fe25519_tobytes(s, y);
+    s[31] ^= fe25519_isnegative(x) << 7;
+}
+
+/*
+ r = a * A + b * B
+ where a = a[0]+256*a[1]+...+256^31 a[31].
+ and b = b[0]+256*b[1]+...+256^31 b[31].
+ B is the Ed25519 base point (x,4/5) with x positive.
+
+ Only used for signatures verification.
+ */
+
+void
+ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
+                                  const ge25519_p3 *A, const unsigned char *b)
+{
+    static const ge25519_precomp Bi[8] = {
+#ifdef HAVE_TI_MODE
+# include "fe_51/base2.h"
+#else
+# include "fe_25_5/base2.h"
+#endif
+    };
+    signed char    aslide[256];
+    signed char    bslide[256];
+    ge25519_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
+    ge25519_p1p1   t;
+    ge25519_p3     u;
+    ge25519_p3     A2;
+    int            i;
+
+    slide_vartime(aslide, a);
+    slide_vartime(bslide, b);
+
+    ge25519_p3_to_cached(&Ai[0], A);
+
+    ge25519_p3_dbl(&t, A);
+    ge25519_p1p1_to_p3(&A2, &t);
+
+    ge25519_add(&t, &A2, &Ai[0]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[1], &u);
+
+    ge25519_add(&t, &A2, &Ai[1]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[2], &u);
+
+    ge25519_add(&t, &A2, &Ai[2]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[3], &u);
+
+    ge25519_add(&t, &A2, &Ai[3]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[4], &u);
+
+    ge25519_add(&t, &A2, &Ai[4]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[5], &u);
+
+    ge25519_add(&t, &A2, &Ai[5]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[6], &u);
+
+    ge25519_add(&t, &A2, &Ai[6]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[7], &u);
+
+    ge25519_p2_0(r);
+
+    for (i = 255; i >= 0; --i) {
+        if (aslide[i] || bslide[i]) {
+            break;
+        }
+    }
+
+    for (; i >= 0; --i) {
+        ge25519_p2_dbl(&t, r);
+
+        if (aslide[i] > 0) {
+            ge25519_p1p1_to_p3(&u, &t);
+            ge25519_add(&t, &u, &Ai[aslide[i] / 2]);
+        } else if (aslide[i] < 0) {
+            ge25519_p1p1_to_p3(&u, &t);
+            ge25519_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+        }
+
+        if (bslide[i] > 0) {
+            ge25519_p1p1_to_p3(&u, &t);
+            ge25519_madd(&t, &u, &Bi[bslide[i] / 2]);
+        } else if (bslide[i] < 0) {
+            ge25519_p1p1_to_p3(&u, &t);
+            ge25519_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
+        }
+
+        ge25519_p1p1_to_p2(r, &t);
+    }
+}
+
+/*
+ h = a * p
+ where a = a[0]+256*a[1]+...+256^31 a[31]
+
+ Preconditions:
+ a[31] <= 127
+
+ p is public
+ */
+
+void
+ge25519_scalarmult(ge25519_p3 *h, const unsigned char *a, const ge25519_p3 *p)
+{
+    signed char     e[64];
+    signed char     carry;
+    ge25519_p1p1    r;
+    ge25519_p2      s;
+    ge25519_p1p1    t2, t3, t4, t5, t6, t7, t8;
+    ge25519_p3      p2, p3, p4, p5, p6, p7, p8;
+    ge25519_cached  pi[8];
+    ge25519_cached  t;
+    int             i;
+
+    ge25519_p3_to_cached(&pi[1 - 1], p);   /* p */
+
+    ge25519_p3_dbl(&t2, p);
+    ge25519_p1p1_to_p3(&p2, &t2);
+    ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */
+
+    ge25519_add(&t3, p, &pi[2 - 1]);
+    ge25519_p1p1_to_p3(&p3, &t3);
+    ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */
+
+    ge25519_p3_dbl(&t4, &p2);
+    ge25519_p1p1_to_p3(&p4, &t4);
+    ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */
+
+    ge25519_add(&t5, p, &pi[4 - 1]);
+    ge25519_p1p1_to_p3(&p5, &t5);
+    ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */
+
+    ge25519_p3_dbl(&t6, &p3);
+    ge25519_p1p1_to_p3(&p6, &t6);
+    ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */
+
+    ge25519_add(&t7, p, &pi[6 - 1]);
+    ge25519_p1p1_to_p3(&p7, &t7);
+    ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */
+
+    ge25519_p3_dbl(&t8, &p4);
+    ge25519_p1p1_to_p3(&p8, &t8);
+    ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */
+
+    for (i = 0; i < 32; ++i) {
+        e[2 * i + 0] = (a[i] >> 0) & 15;
+        e[2 * i + 1] = (a[i] >> 4) & 15;
+    }
+    /* each e[i] is between 0 and 15 */
+    /* e[63] is between 0 and 7 */
+
+    carry = 0;
+    for (i = 0; i < 63; ++i) {
+        e[i] += carry;
+        carry = e[i] + 8;
+        carry >>= 4;
+        e[i] -= carry * ((signed char) 1 << 4);
+    }
+    e[63] += carry;
+    /* each e[i] is between -8 and 8 */
+
+    ge25519_p3_0(h);
+
+    for (i = 63; i != 0; i--) {
+        ge25519_cmov8_cached(&t, pi, e[i]);
+        ge25519_add(&r, h, &t);
+
+        ge25519_p1p1_to_p2(&s, &r);
+        ge25519_p2_dbl(&r, &s);
+        ge25519_p1p1_to_p2(&s, &r);
+        ge25519_p2_dbl(&r, &s);
+        ge25519_p1p1_to_p2(&s, &r);
+        ge25519_p2_dbl(&r, &s);
+        ge25519_p1p1_to_p2(&s, &r);
+        ge25519_p2_dbl(&r, &s);
+
+        ge25519_p1p1_to_p3(h, &r);  /* *16 */
+    }
+    ge25519_cmov8_cached(&t, pi, e[i]);
+    ge25519_add(&r, h, &t);
+
+    ge25519_p1p1_to_p3(h, &r);
+}
+
+/*
+ h = a * B (with precomputation)
+ where a = a[0]+256*a[1]+...+256^31 a[31]
+ B is the Ed25519 base point (x,4/5) with x positive
+ (as bytes: 0x5866666666666666666666666666666666666666666666666666666666666666)
+
+ Preconditions:
+ a[31] <= 127
+ */
+
+void
+ge25519_scalarmult_base(ge25519_p3 *h, const unsigned char *a)
+{
+    signed char     e[64];
+    signed char     carry;
+    ge25519_p1p1    r;
+    ge25519_p2      s;
+    ge25519_precomp t;
+    int             i;
+
+    for (i = 0; i < 32; ++i) {
+        e[2 * i + 0] = (a[i] >> 0) & 15;
+        e[2 * i + 1] = (a[i] >> 4) & 15;
+    }
+    /* each e[i] is between 0 and 15 */
+    /* e[63] is between 0 and 7 */
+
+    carry = 0;
+    for (i = 0; i < 63; ++i) {
+        e[i] += carry;
+        carry = e[i] + 8;
+        carry >>= 4;
+        e[i] -= carry * ((signed char) 1 << 4);
+    }
+    e[63] += carry;
+    /* each e[i] is between -8 and 8 */
+
+    ge25519_p3_0(h);
+
+    for (i = 1; i < 64; i += 2) {
+        ge25519_cmov8_base(&t, i / 2, e[i]);
+        ge25519_madd(&r, h, &t);
+        ge25519_p1p1_to_p3(h, &r);
+    }
+
+    ge25519_p3_dbl(&r, h);
+    ge25519_p1p1_to_p2(&s, &r);
+    ge25519_p2_dbl(&r, &s);
+    ge25519_p1p1_to_p2(&s, &r);
+    ge25519_p2_dbl(&r, &s);
+    ge25519_p1p1_to_p2(&s, &r);
+    ge25519_p2_dbl(&r, &s);
+    ge25519_p1p1_to_p3(h, &r);
+
+    for (i = 0; i < 64; i += 2) {
+        ge25519_cmov8_base(&t, i / 2, e[i]);
+        ge25519_madd(&r, h, &t);
+        ge25519_p1p1_to_p3(h, &r);
+    }
+}
+
+/* multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493 */
+static void
+ge25519_mul_l(ge25519_p3 *r, const ge25519_p3 *A)
+{
+    static const signed char aslide[253] = {
+        13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+    };
+    ge25519_cached Ai[8];
+    ge25519_p1p1   t;
+    ge25519_p3     u;
+    ge25519_p3     A2;
+    int            i;
+
+    ge25519_p3_to_cached(&Ai[0], A);
+    ge25519_p3_dbl(&t, A);
+    ge25519_p1p1_to_p3(&A2, &t);
+    ge25519_add(&t, &A2, &Ai[0]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[1], &u);
+    ge25519_add(&t, &A2, &Ai[1]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[2], &u);
+    ge25519_add(&t, &A2, &Ai[2]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[3], &u);
+    ge25519_add(&t, &A2, &Ai[3]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[4], &u);
+    ge25519_add(&t, &A2, &Ai[4]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[5], &u);
+    ge25519_add(&t, &A2, &Ai[5]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[6], &u);
+    ge25519_add(&t, &A2, &Ai[6]);
+    ge25519_p1p1_to_p3(&u, &t);
+    ge25519_p3_to_cached(&Ai[7], &u);
+
+    ge25519_p3_0(r);
+
+    for (i = 252; i >= 0; --i) {
+        ge25519_p3_dbl(&t, r);
+
+        if (aslide[i] > 0) {
+            ge25519_p1p1_to_p3(&u, &t);
+            ge25519_add(&t, &u, &Ai[aslide[i] / 2]);
+        } else if (aslide[i] < 0) {
+            ge25519_p1p1_to_p3(&u, &t);
+            ge25519_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+        }
+
+        ge25519_p1p1_to_p3(r, &t);
+    }
+}
+
+int
+ge25519_is_on_curve(const ge25519_p3 *p)
+{
+    fe25519 x2;
+    fe25519 y2;
+    fe25519 z2;
+    fe25519 z4;
+    fe25519 t0;
+    fe25519 t1;
+
+    fe25519_sq(x2, p->X);
+    fe25519_sq(y2, p->Y);
+    fe25519_sq(z2, p->Z);
+    fe25519_sub(t0, y2, x2);
+    fe25519_mul(t0, t0, z2);
+
+    fe25519_mul(t1, x2, y2);
+    fe25519_mul(t1, t1, d);
+    fe25519_sq(z4, z2);
+    fe25519_add(t1, t1, z4);
+    fe25519_sub(t0, t0, t1);
+
+    return fe25519_iszero(t0);
+}
+
+int
+ge25519_is_on_main_subgroup(const ge25519_p3 *p)
+{
+    ge25519_p3 pl;
+
+    ge25519_mul_l(&pl, p);
+
+    return fe25519_iszero(pl.X);
+}
+
+int
+ge25519_is_canonical(const unsigned char *s)
+{
+    unsigned char c;
+    unsigned char d;
+    unsigned int  i;
+
+    c = (s[31] & 0x7f) ^ 0x7f;
+    for (i = 30; i > 0; i--) {
+        c |= s[i] ^ 0xff;
+    }
+    c = (((unsigned int) c) - 1U) >> 8;
+    d = (0xed - 1U - (unsigned int) s[0]) >> 8;
+
+    return 1 - (c & d & 1);
+}
+
+int
+ge25519_has_small_order(const unsigned char s[32])
+{
+    CRYPTO_ALIGN(16)
+    static const unsigned char blacklist[][32] = {
+        /* 0 (order 4) */
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+        /* 1 (order 1) */
+        { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+        /* 2707385501144840649318225287225658788936804267575313519463743609750303402022
+           (order 8) */
+        { 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4,
+          0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6,
+          0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 },
+        /* 55188659117513257062467267217118295137698188065244968500265048394206261417927
+           (order 8) */
+        { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b,
+          0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39,
+          0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a },
+        /* p-1 (order 2) */
+        { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+        /* p (=0, order 4) */
+        { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+        /* p+1 (=1, order 1) */
+        { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }
+    };
+    unsigned char c[7] = { 0 };
+    unsigned int  k;
+    size_t        i, j;
+
+    COMPILER_ASSERT(7 == sizeof blacklist / sizeof blacklist[0]);
+    for (j = 0; j < 31; j++) {
+        for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+            c[i] |= s[j] ^ blacklist[i][j];
+        }
+    }
+    for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+        c[i] |= (s[j] & 0x7f) ^ blacklist[i][j];
+    }
+    k = 0;
+    for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+        k |= (c[i] - 1);
+    }
+    return (int) ((k >> 8) & 1);
+}
+
+/*
+ Input:
+ a[0]+256*a[1]+...+256^31*a[31] = a
+ b[0]+256*b[1]+...+256^31*b[31] = b
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = (ab) mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ */
+
+void
+sc25519_mul(unsigned char s[32], const unsigned char a[32], const unsigned char b[32])
+{
+    int64_t a0  = 2097151 & load_3(a);
+    int64_t a1  = 2097151 & (load_4(a + 2) >> 5);
+    int64_t a2  = 2097151 & (load_3(a + 5) >> 2);
+    int64_t a3  = 2097151 & (load_4(a + 7) >> 7);
+    int64_t a4  = 2097151 & (load_4(a + 10) >> 4);
+    int64_t a5  = 2097151 & (load_3(a + 13) >> 1);
+    int64_t a6  = 2097151 & (load_4(a + 15) >> 6);
+    int64_t a7  = 2097151 & (load_3(a + 18) >> 3);
+    int64_t a8  = 2097151 & load_3(a + 21);
+    int64_t a9  = 2097151 & (load_4(a + 23) >> 5);
+    int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
+    int64_t a11 = (load_4(a + 28) >> 7);
+
+    int64_t b0  = 2097151 & load_3(b);
+    int64_t b1  = 2097151 & (load_4(b + 2) >> 5);
+    int64_t b2  = 2097151 & (load_3(b + 5) >> 2);
+    int64_t b3  = 2097151 & (load_4(b + 7) >> 7);
+    int64_t b4  = 2097151 & (load_4(b + 10) >> 4);
+    int64_t b5  = 2097151 & (load_3(b + 13) >> 1);
+    int64_t b6  = 2097151 & (load_4(b + 15) >> 6);
+    int64_t b7  = 2097151 & (load_3(b + 18) >> 3);
+    int64_t b8  = 2097151 & load_3(b + 21);
+    int64_t b9  = 2097151 & (load_4(b + 23) >> 5);
+    int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
+    int64_t b11 = (load_4(b + 28) >> 7);
+
+    int64_t s0;
+    int64_t s1;
+    int64_t s2;
+    int64_t s3;
+    int64_t s4;
+    int64_t s5;
+    int64_t s6;
+    int64_t s7;
+    int64_t s8;
+    int64_t s9;
+    int64_t s10;
+    int64_t s11;
+    int64_t s12;
+    int64_t s13;
+    int64_t s14;
+    int64_t s15;
+    int64_t s16;
+    int64_t s17;
+    int64_t s18;
+    int64_t s19;
+    int64_t s20;
+    int64_t s21;
+    int64_t s22;
+    int64_t s23;
+
+    int64_t carry0;
+    int64_t carry1;
+    int64_t carry2;
+    int64_t carry3;
+    int64_t carry4;
+    int64_t carry5;
+    int64_t carry6;
+    int64_t carry7;
+    int64_t carry8;
+    int64_t carry9;
+    int64_t carry10;
+    int64_t carry11;
+    int64_t carry12;
+    int64_t carry13;
+    int64_t carry14;
+    int64_t carry15;
+    int64_t carry16;
+    int64_t carry17;
+    int64_t carry18;
+    int64_t carry19;
+    int64_t carry20;
+    int64_t carry21;
+    int64_t carry22;
+
+    s0 = a0 * b0;
+    s1 = a0 * b1 + a1 * b0;
+    s2 = a0 * b2 + a1 * b1 + a2 * b0;
+    s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
+    s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
+    s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
+    s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
+    s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
+         a6 * b1 + a7 * b0;
+    s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
+         a6 * b2 + a7 * b1 + a8 * b0;
+    s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
+         a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
+    s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
+          a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
+    s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
+          a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
+    s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 +
+          a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
+    s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 +
+          a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
+    s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 +
+          a9 * b5 + a10 * b4 + a11 * b3;
+    s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 +
+          a10 * b5 + a11 * b4;
+    s16 =
+        a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
+    s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
+    s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
+    s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
+    s20 = a9 * b11 + a10 * b10 + a11 * b9;
+    s21 = a10 * b11 + a11 * b10;
+    s22 = a11 * b11;
+    s23 = 0;
+
+    carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+    s13 += carry12;
+    s12 -= carry12 * ((uint64_t) 1L << 21);
+    carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+    s15 += carry14;
+    s14 -= carry14 * ((uint64_t) 1L << 21);
+    carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+    s17 += carry16;
+    s16 -= carry16 * ((uint64_t) 1L << 21);
+    carry18 = (s18 + (int64_t) (1L << 20)) >> 21;
+    s19 += carry18;
+    s18 -= carry18 * ((uint64_t) 1L << 21);
+    carry20 = (s20 + (int64_t) (1L << 20)) >> 21;
+    s21 += carry20;
+    s20 -= carry20 * ((uint64_t) 1L << 21);
+    carry22 = (s22 + (int64_t) (1L << 20)) >> 21;
+    s23 += carry22;
+    s22 -= carry22 * ((uint64_t) 1L << 21);
+
+    carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+    carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+    s14 += carry13;
+    s13 -= carry13 * ((uint64_t) 1L << 21);
+    carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+    s16 += carry15;
+    s15 -= carry15 * ((uint64_t) 1L << 21);
+    carry17 = (s17 + (int64_t) (1L << 20)) >> 21;
+    s18 += carry17;
+    s17 -= carry17 * ((uint64_t) 1L << 21);
+    carry19 = (s19 + (int64_t) (1L << 20)) >> 21;
+    s20 += carry19;
+    s19 -= carry19 * ((uint64_t) 1L << 21);
+    carry21 = (s21 + (int64_t) (1L << 20)) >> 21;
+    s22 += carry21;
+    s21 -= carry21 * ((uint64_t) 1L << 21);
+
+    s11 += s23 * 666643;
+    s12 += s23 * 470296;
+    s13 += s23 * 654183;
+    s14 -= s23 * 997805;
+    s15 += s23 * 136657;
+    s16 -= s23 * 683901;
+
+    s10 += s22 * 666643;
+    s11 += s22 * 470296;
+    s12 += s22 * 654183;
+    s13 -= s22 * 997805;
+    s14 += s22 * 136657;
+    s15 -= s22 * 683901;
+
+    s9 += s21 * 666643;
+    s10 += s21 * 470296;
+    s11 += s21 * 654183;
+    s12 -= s21 * 997805;
+    s13 += s21 * 136657;
+    s14 -= s21 * 683901;
+
+    s8 += s20 * 666643;
+    s9 += s20 * 470296;
+    s10 += s20 * 654183;
+    s11 -= s20 * 997805;
+    s12 += s20 * 136657;
+    s13 -= s20 * 683901;
+
+    s7 += s19 * 666643;
+    s8 += s19 * 470296;
+    s9 += s19 * 654183;
+    s10 -= s19 * 997805;
+    s11 += s19 * 136657;
+    s12 -= s19 * 683901;
+
+    s6 += s18 * 666643;
+    s7 += s18 * 470296;
+    s8 += s18 * 654183;
+    s9 -= s18 * 997805;
+    s10 += s18 * 136657;
+    s11 -= s18 * 683901;
+
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+    s13 += carry12;
+    s12 -= carry12 * ((uint64_t) 1L << 21);
+    carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+    s15 += carry14;
+    s14 -= carry14 * ((uint64_t) 1L << 21);
+    carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+    s17 += carry16;
+    s16 -= carry16 * ((uint64_t) 1L << 21);
+
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+    carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+    s14 += carry13;
+    s13 -= carry13 * ((uint64_t) 1L << 21);
+    carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+    s16 += carry15;
+    s15 -= carry15 * ((uint64_t) 1L << 21);
+
+    s5 += s17 * 666643;
+    s6 += s17 * 470296;
+    s7 += s17 * 654183;
+    s8 -= s17 * 997805;
+    s9 += s17 * 136657;
+    s10 -= s17 * 683901;
+
+    s4 += s16 * 666643;
+    s5 += s16 * 470296;
+    s6 += s16 * 654183;
+    s7 -= s16 * 997805;
+    s8 += s16 * 136657;
+    s9 -= s16 * 683901;
+
+    s3 += s15 * 666643;
+    s4 += s15 * 470296;
+    s5 += s15 * 654183;
+    s6 -= s15 * 997805;
+    s7 += s15 * 136657;
+    s8 -= s15 * 683901;
+
+    s2 += s14 * 666643;
+    s3 += s14 * 470296;
+    s4 += s14 * 654183;
+    s5 -= s14 * 997805;
+    s6 += s14 * 136657;
+    s7 -= s14 * 683901;
+
+    s1 += s13 * 666643;
+    s2 += s13 * 470296;
+    s3 += s13 * 654183;
+    s4 -= s13 * 997805;
+    s5 += s13 * 136657;
+    s6 -= s13 * 683901;
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+    s12 = 0;
+
+    carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+
+    carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+    s12 = 0;
+
+    carry0 = s0 >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry1 = s1 >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry2 = s2 >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry3 = s3 >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry4 = s4 >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry5 = s5 >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry6 = s6 >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry7 = s7 >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry8 = s8 >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry9 = s9 >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry10 = s10 >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry11 = s11 >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+
+    carry0 = s0 >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry1 = s1 >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry2 = s2 >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry3 = s3 >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry4 = s4 >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry5 = s5 >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry6 = s6 >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry7 = s7 >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry8 = s8 >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry9 = s9 >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry10 = s10 >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+
+    s[0]  = s0 >> 0;
+    s[1]  = s0 >> 8;
+    s[2]  = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
+    s[3]  = s1 >> 3;
+    s[4]  = s1 >> 11;
+    s[5]  = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
+    s[6]  = s2 >> 6;
+    s[7]  = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
+    s[8]  = s3 >> 1;
+    s[9]  = s3 >> 9;
+    s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
+    s[11] = s4 >> 4;
+    s[12] = s4 >> 12;
+    s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
+    s[14] = s5 >> 7;
+    s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
+    s[16] = s6 >> 2;
+    s[17] = s6 >> 10;
+    s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
+    s[19] = s7 >> 5;
+    s[20] = s7 >> 13;
+    s[21] = s8 >> 0;
+    s[22] = s8 >> 8;
+    s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
+    s[24] = s9 >> 3;
+    s[25] = s9 >> 11;
+    s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
+    s[27] = s10 >> 6;
+    s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
+    s[29] = s11 >> 1;
+    s[30] = s11 >> 9;
+    s[31] = s11 >> 17;
+}
+
+/*
+ Input:
+ a[0]+256*a[1]+...+256^31*a[31] = a
+ b[0]+256*b[1]+...+256^31*b[31] = b
+ c[0]+256*c[1]+...+256^31*c[31] = c
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ */
+
+void
+sc25519_muladd(unsigned char s[32], const unsigned char a[32],
+               const unsigned char b[32], const unsigned char c[32])
+{
+    int64_t a0  = 2097151 & load_3(a);
+    int64_t a1  = 2097151 & (load_4(a + 2) >> 5);
+    int64_t a2  = 2097151 & (load_3(a + 5) >> 2);
+    int64_t a3  = 2097151 & (load_4(a + 7) >> 7);
+    int64_t a4  = 2097151 & (load_4(a + 10) >> 4);
+    int64_t a5  = 2097151 & (load_3(a + 13) >> 1);
+    int64_t a6  = 2097151 & (load_4(a + 15) >> 6);
+    int64_t a7  = 2097151 & (load_3(a + 18) >> 3);
+    int64_t a8  = 2097151 & load_3(a + 21);
+    int64_t a9  = 2097151 & (load_4(a + 23) >> 5);
+    int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
+    int64_t a11 = (load_4(a + 28) >> 7);
+
+    int64_t b0  = 2097151 & load_3(b);
+    int64_t b1  = 2097151 & (load_4(b + 2) >> 5);
+    int64_t b2  = 2097151 & (load_3(b + 5) >> 2);
+    int64_t b3  = 2097151 & (load_4(b + 7) >> 7);
+    int64_t b4  = 2097151 & (load_4(b + 10) >> 4);
+    int64_t b5  = 2097151 & (load_3(b + 13) >> 1);
+    int64_t b6  = 2097151 & (load_4(b + 15) >> 6);
+    int64_t b7  = 2097151 & (load_3(b + 18) >> 3);
+    int64_t b8  = 2097151 & load_3(b + 21);
+    int64_t b9  = 2097151 & (load_4(b + 23) >> 5);
+    int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
+    int64_t b11 = (load_4(b + 28) >> 7);
+
+    int64_t c0  = 2097151 & load_3(c);
+    int64_t c1  = 2097151 & (load_4(c + 2) >> 5);
+    int64_t c2  = 2097151 & (load_3(c + 5) >> 2);
+    int64_t c3  = 2097151 & (load_4(c + 7) >> 7);
+    int64_t c4  = 2097151 & (load_4(c + 10) >> 4);
+    int64_t c5  = 2097151 & (load_3(c + 13) >> 1);
+    int64_t c6  = 2097151 & (load_4(c + 15) >> 6);
+    int64_t c7  = 2097151 & (load_3(c + 18) >> 3);
+    int64_t c8  = 2097151 & load_3(c + 21);
+    int64_t c9  = 2097151 & (load_4(c + 23) >> 5);
+    int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
+    int64_t c11 = (load_4(c + 28) >> 7);
+
+    int64_t s0;
+    int64_t s1;
+    int64_t s2;
+    int64_t s3;
+    int64_t s4;
+    int64_t s5;
+    int64_t s6;
+    int64_t s7;
+    int64_t s8;
+    int64_t s9;
+    int64_t s10;
+    int64_t s11;
+    int64_t s12;
+    int64_t s13;
+    int64_t s14;
+    int64_t s15;
+    int64_t s16;
+    int64_t s17;
+    int64_t s18;
+    int64_t s19;
+    int64_t s20;
+    int64_t s21;
+    int64_t s22;
+    int64_t s23;
+
+    int64_t carry0;
+    int64_t carry1;
+    int64_t carry2;
+    int64_t carry3;
+    int64_t carry4;
+    int64_t carry5;
+    int64_t carry6;
+    int64_t carry7;
+    int64_t carry8;
+    int64_t carry9;
+    int64_t carry10;
+    int64_t carry11;
+    int64_t carry12;
+    int64_t carry13;
+    int64_t carry14;
+    int64_t carry15;
+    int64_t carry16;
+    int64_t carry17;
+    int64_t carry18;
+    int64_t carry19;
+    int64_t carry20;
+    int64_t carry21;
+    int64_t carry22;
+
+    s0 = c0 + a0 * b0;
+    s1 = c1 + a0 * b1 + a1 * b0;
+    s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
+    s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
+    s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
+    s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
+    s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 +
+         a6 * b0;
+    s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
+         a6 * b1 + a7 * b0;
+    s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
+         a6 * b2 + a7 * b1 + a8 * b0;
+    s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
+         a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
+    s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
+          a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
+    s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
+          a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
+    s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 +
+          a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
+    s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 +
+          a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
+    s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 +
+          a9 * b5 + a10 * b4 + a11 * b3;
+    s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 +
+          a10 * b5 + a11 * b4;
+    s16 =
+        a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
+    s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
+    s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
+    s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
+    s20 = a9 * b11 + a10 * b10 + a11 * b9;
+    s21 = a10 * b11 + a11 * b10;
+    s22 = a11 * b11;
+    s23 = 0;
+
+    carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+    s13 += carry12;
+    s12 -= carry12 * ((uint64_t) 1L << 21);
+    carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+    s15 += carry14;
+    s14 -= carry14 * ((uint64_t) 1L << 21);
+    carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+    s17 += carry16;
+    s16 -= carry16 * ((uint64_t) 1L << 21);
+    carry18 = (s18 + (int64_t) (1L << 20)) >> 21;
+    s19 += carry18;
+    s18 -= carry18 * ((uint64_t) 1L << 21);
+    carry20 = (s20 + (int64_t) (1L << 20)) >> 21;
+    s21 += carry20;
+    s20 -= carry20 * ((uint64_t) 1L << 21);
+    carry22 = (s22 + (int64_t) (1L << 20)) >> 21;
+    s23 += carry22;
+    s22 -= carry22 * ((uint64_t) 1L << 21);
+
+    carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+    carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+    s14 += carry13;
+    s13 -= carry13 * ((uint64_t) 1L << 21);
+    carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+    s16 += carry15;
+    s15 -= carry15 * ((uint64_t) 1L << 21);
+    carry17 = (s17 + (int64_t) (1L << 20)) >> 21;
+    s18 += carry17;
+    s17 -= carry17 * ((uint64_t) 1L << 21);
+    carry19 = (s19 + (int64_t) (1L << 20)) >> 21;
+    s20 += carry19;
+    s19 -= carry19 * ((uint64_t) 1L << 21);
+    carry21 = (s21 + (int64_t) (1L << 20)) >> 21;
+    s22 += carry21;
+    s21 -= carry21 * ((uint64_t) 1L << 21);
+
+    s11 += s23 * 666643;
+    s12 += s23 * 470296;
+    s13 += s23 * 654183;
+    s14 -= s23 * 997805;
+    s15 += s23 * 136657;
+    s16 -= s23 * 683901;
+
+    s10 += s22 * 666643;
+    s11 += s22 * 470296;
+    s12 += s22 * 654183;
+    s13 -= s22 * 997805;
+    s14 += s22 * 136657;
+    s15 -= s22 * 683901;
+
+    s9 += s21 * 666643;
+    s10 += s21 * 470296;
+    s11 += s21 * 654183;
+    s12 -= s21 * 997805;
+    s13 += s21 * 136657;
+    s14 -= s21 * 683901;
+
+    s8 += s20 * 666643;
+    s9 += s20 * 470296;
+    s10 += s20 * 654183;
+    s11 -= s20 * 997805;
+    s12 += s20 * 136657;
+    s13 -= s20 * 683901;
+
+    s7 += s19 * 666643;
+    s8 += s19 * 470296;
+    s9 += s19 * 654183;
+    s10 -= s19 * 997805;
+    s11 += s19 * 136657;
+    s12 -= s19 * 683901;
+
+    s6 += s18 * 666643;
+    s7 += s18 * 470296;
+    s8 += s18 * 654183;
+    s9 -= s18 * 997805;
+    s10 += s18 * 136657;
+    s11 -= s18 * 683901;
+
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+    s13 += carry12;
+    s12 -= carry12 * ((uint64_t) 1L << 21);
+    carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+    s15 += carry14;
+    s14 -= carry14 * ((uint64_t) 1L << 21);
+    carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+    s17 += carry16;
+    s16 -= carry16 * ((uint64_t) 1L << 21);
+
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+    carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+    s14 += carry13;
+    s13 -= carry13 * ((uint64_t) 1L << 21);
+    carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+    s16 += carry15;
+    s15 -= carry15 * ((uint64_t) 1L << 21);
+
+    s5 += s17 * 666643;
+    s6 += s17 * 470296;
+    s7 += s17 * 654183;
+    s8 -= s17 * 997805;
+    s9 += s17 * 136657;
+    s10 -= s17 * 683901;
+
+    s4 += s16 * 666643;
+    s5 += s16 * 470296;
+    s6 += s16 * 654183;
+    s7 -= s16 * 997805;
+    s8 += s16 * 136657;
+    s9 -= s16 * 683901;
+
+    s3 += s15 * 666643;
+    s4 += s15 * 470296;
+    s5 += s15 * 654183;
+    s6 -= s15 * 997805;
+    s7 += s15 * 136657;
+    s8 -= s15 * 683901;
+
+    s2 += s14 * 666643;
+    s3 += s14 * 470296;
+    s4 += s14 * 654183;
+    s5 -= s14 * 997805;
+    s6 += s14 * 136657;
+    s7 -= s14 * 683901;
+
+    s1 += s13 * 666643;
+    s2 += s13 * 470296;
+    s3 += s13 * 654183;
+    s4 -= s13 * 997805;
+    s5 += s13 * 136657;
+    s6 -= s13 * 683901;
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+    s12 = 0;
+
+    carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+
+    carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+    s12 = 0;
+
+    carry0 = s0 >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry1 = s1 >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry2 = s2 >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry3 = s3 >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry4 = s4 >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry5 = s5 >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry6 = s6 >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry7 = s7 >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry8 = s8 >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry9 = s9 >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry10 = s10 >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry11 = s11 >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+
+    carry0 = s0 >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry1 = s1 >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry2 = s2 >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry3 = s3 >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry4 = s4 >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry5 = s5 >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry6 = s6 >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry7 = s7 >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry8 = s8 >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry9 = s9 >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry10 = s10 >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+
+    s[0]  = s0 >> 0;
+    s[1]  = s0 >> 8;
+    s[2]  = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
+    s[3]  = s1 >> 3;
+    s[4]  = s1 >> 11;
+    s[5]  = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
+    s[6]  = s2 >> 6;
+    s[7]  = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
+    s[8]  = s3 >> 1;
+    s[9]  = s3 >> 9;
+    s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
+    s[11] = s4 >> 4;
+    s[12] = s4 >> 12;
+    s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
+    s[14] = s5 >> 7;
+    s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
+    s[16] = s6 >> 2;
+    s[17] = s6 >> 10;
+    s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
+    s[19] = s7 >> 5;
+    s[20] = s7 >> 13;
+    s[21] = s8 >> 0;
+    s[22] = s8 >> 8;
+    s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
+    s[24] = s9 >> 3;
+    s[25] = s9 >> 11;
+    s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
+    s[27] = s10 >> 6;
+    s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
+    s[29] = s11 >> 1;
+    s[30] = s11 >> 9;
+    s[31] = s11 >> 17;
+}
+
+/*
+ Input:
+ a[0]+256*a[1]+...+256^31*a[31] = a
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = a^2 mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ */
+
+static inline void
+sc25519_sq(unsigned char *s, const unsigned char *a)
+{
+    sc25519_mul(s, a, a);
+}
+
+/*
+ Input:
+ s[0]+256*a[1]+...+256^31*a[31] = a
+ n
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = x * s^(s^n) mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ Overwrites s in place.
+ */
+
+static inline void
+sc25519_sqmul(unsigned char s[32], const int n, const unsigned char a[32])
+{
+    int i;
+
+    for (i = 0; i < n; i++) {
+        sc25519_sq(s, s);
+    }
+    sc25519_mul(s, s, a);
+}
+
+void
+sc25519_invert(unsigned char recip[32], const unsigned char s[32])
+{
+    unsigned char _10[32], _100[32], _11[32], _101[32], _111[32],
+        _1001[32], _1011[32], _1111[32];
+
+    sc25519_sq(_10, s);
+    sc25519_sq(_100, _10);
+    sc25519_mul(_11, _10, s);
+    sc25519_mul(_101, _10, _11);
+    sc25519_mul(_111, _10, _101);
+    sc25519_mul(_1001, _10, _111);
+    sc25519_mul(_1011, _10, _1001);
+    sc25519_mul(_1111, _100, _1011);
+    sc25519_mul(recip, _1111, s);
+
+    sc25519_sqmul(recip, 123 + 3, _101);
+    sc25519_sqmul(recip, 2 + 2, _11);
+    sc25519_sqmul(recip, 1 + 4, _1111);
+    sc25519_sqmul(recip, 1 + 4, _1111);
+    sc25519_sqmul(recip, 4, _1001);
+    sc25519_sqmul(recip, 2, _11);
+    sc25519_sqmul(recip, 1 + 4, _1111);
+    sc25519_sqmul(recip, 1 + 3, _101);
+    sc25519_sqmul(recip, 3 + 3, _101);
+    sc25519_sqmul(recip, 3, _111);
+    sc25519_sqmul(recip, 1 + 4, _1111);
+    sc25519_sqmul(recip, 2 + 3, _111);
+    sc25519_sqmul(recip, 2 + 2, _11);
+    sc25519_sqmul(recip, 1 + 4, _1011);
+    sc25519_sqmul(recip, 2 + 4, _1011);
+    sc25519_sqmul(recip, 6 + 4, _1001);
+    sc25519_sqmul(recip, 2 + 2, _11);
+    sc25519_sqmul(recip, 3 + 2, _11);
+    sc25519_sqmul(recip, 3 + 2, _11);
+    sc25519_sqmul(recip, 1 + 4, _1001);
+    sc25519_sqmul(recip, 1 + 3, _111);
+    sc25519_sqmul(recip, 2 + 4, _1111);
+    sc25519_sqmul(recip, 1 + 4, _1011);
+    sc25519_sqmul(recip, 3, _101);
+    sc25519_sqmul(recip, 2 + 4, _1111);
+    sc25519_sqmul(recip, 3, _101);
+    sc25519_sqmul(recip, 1 + 2, _11);
+}
+
+/*
+ Input:
+ s[0]+256*s[1]+...+256^63*s[63] = s
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = s mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ Overwrites s in place.
+ */
+
+void
+sc25519_reduce(unsigned char s[64])
+{
+    int64_t s0  = 2097151 & load_3(s);
+    int64_t s1  = 2097151 & (load_4(s + 2) >> 5);
+    int64_t s2  = 2097151 & (load_3(s + 5) >> 2);
+    int64_t s3  = 2097151 & (load_4(s + 7) >> 7);
+    int64_t s4  = 2097151 & (load_4(s + 10) >> 4);
+    int64_t s5  = 2097151 & (load_3(s + 13) >> 1);
+    int64_t s6  = 2097151 & (load_4(s + 15) >> 6);
+    int64_t s7  = 2097151 & (load_3(s + 18) >> 3);
+    int64_t s8  = 2097151 & load_3(s + 21);
+    int64_t s9  = 2097151 & (load_4(s + 23) >> 5);
+    int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
+    int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
+    int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
+    int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
+    int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
+    int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
+    int64_t s16 = 2097151 & load_3(s + 42);
+    int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
+    int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
+    int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
+    int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
+    int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
+    int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
+    int64_t s23 = (load_4(s + 60) >> 3);
+
+    int64_t carry0;
+    int64_t carry1;
+    int64_t carry2;
+    int64_t carry3;
+    int64_t carry4;
+    int64_t carry5;
+    int64_t carry6;
+    int64_t carry7;
+    int64_t carry8;
+    int64_t carry9;
+    int64_t carry10;
+    int64_t carry11;
+    int64_t carry12;
+    int64_t carry13;
+    int64_t carry14;
+    int64_t carry15;
+    int64_t carry16;
+
+    s11 += s23 * 666643;
+    s12 += s23 * 470296;
+    s13 += s23 * 654183;
+    s14 -= s23 * 997805;
+    s15 += s23 * 136657;
+    s16 -= s23 * 683901;
+
+    s10 += s22 * 666643;
+    s11 += s22 * 470296;
+    s12 += s22 * 654183;
+    s13 -= s22 * 997805;
+    s14 += s22 * 136657;
+    s15 -= s22 * 683901;
+
+    s9 += s21 * 666643;
+    s10 += s21 * 470296;
+    s11 += s21 * 654183;
+    s12 -= s21 * 997805;
+    s13 += s21 * 136657;
+    s14 -= s21 * 683901;
+
+    s8 += s20 * 666643;
+    s9 += s20 * 470296;
+    s10 += s20 * 654183;
+    s11 -= s20 * 997805;
+    s12 += s20 * 136657;
+    s13 -= s20 * 683901;
+
+    s7 += s19 * 666643;
+    s8 += s19 * 470296;
+    s9 += s19 * 654183;
+    s10 -= s19 * 997805;
+    s11 += s19 * 136657;
+    s12 -= s19 * 683901;
+
+    s6 += s18 * 666643;
+    s7 += s18 * 470296;
+    s8 += s18 * 654183;
+    s9 -= s18 * 997805;
+    s10 += s18 * 136657;
+    s11 -= s18 * 683901;
+
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+    s13 += carry12;
+    s12 -= carry12 * ((uint64_t) 1L << 21);
+    carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+    s15 += carry14;
+    s14 -= carry14 * ((uint64_t) 1L << 21);
+    carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+    s17 += carry16;
+    s16 -= carry16 * ((uint64_t) 1L << 21);
+
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+    carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+    s14 += carry13;
+    s13 -= carry13 * ((uint64_t) 1L << 21);
+    carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+    s16 += carry15;
+    s15 -= carry15 * ((uint64_t) 1L << 21);
+
+    s5 += s17 * 666643;
+    s6 += s17 * 470296;
+    s7 += s17 * 654183;
+    s8 -= s17 * 997805;
+    s9 += s17 * 136657;
+    s10 -= s17 * 683901;
+
+    s4 += s16 * 666643;
+    s5 += s16 * 470296;
+    s6 += s16 * 654183;
+    s7 -= s16 * 997805;
+    s8 += s16 * 136657;
+    s9 -= s16 * 683901;
+
+    s3 += s15 * 666643;
+    s4 += s15 * 470296;
+    s5 += s15 * 654183;
+    s6 -= s15 * 997805;
+    s7 += s15 * 136657;
+    s8 -= s15 * 683901;
+
+    s2 += s14 * 666643;
+    s3 += s14 * 470296;
+    s4 += s14 * 654183;
+    s5 -= s14 * 997805;
+    s6 += s14 * 136657;
+    s7 -= s14 * 683901;
+
+    s1 += s13 * 666643;
+    s2 += s13 * 470296;
+    s3 += s13 * 654183;
+    s4 -= s13 * 997805;
+    s5 += s13 * 136657;
+    s6 -= s13 * 683901;
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+    s12 = 0;
+
+    carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+
+    carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+    s12 = 0;
+
+    carry0 = s0 >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry1 = s1 >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry2 = s2 >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry3 = s3 >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry4 = s4 >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry5 = s5 >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry6 = s6 >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry7 = s7 >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry8 = s8 >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry9 = s9 >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry10 = s10 >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+    carry11 = s11 >> 21;
+    s12 += carry11;
+    s11 -= carry11 * ((uint64_t) 1L << 21);
+
+    s0 += s12 * 666643;
+    s1 += s12 * 470296;
+    s2 += s12 * 654183;
+    s3 -= s12 * 997805;
+    s4 += s12 * 136657;
+    s5 -= s12 * 683901;
+
+    carry0 = s0 >> 21;
+    s1 += carry0;
+    s0 -= carry0 * ((uint64_t) 1L << 21);
+    carry1 = s1 >> 21;
+    s2 += carry1;
+    s1 -= carry1 * ((uint64_t) 1L << 21);
+    carry2 = s2 >> 21;
+    s3 += carry2;
+    s2 -= carry2 * ((uint64_t) 1L << 21);
+    carry3 = s3 >> 21;
+    s4 += carry3;
+    s3 -= carry3 * ((uint64_t) 1L << 21);
+    carry4 = s4 >> 21;
+    s5 += carry4;
+    s4 -= carry4 * ((uint64_t) 1L << 21);
+    carry5 = s5 >> 21;
+    s6 += carry5;
+    s5 -= carry5 * ((uint64_t) 1L << 21);
+    carry6 = s6 >> 21;
+    s7 += carry6;
+    s6 -= carry6 * ((uint64_t) 1L << 21);
+    carry7 = s7 >> 21;
+    s8 += carry7;
+    s7 -= carry7 * ((uint64_t) 1L << 21);
+    carry8 = s8 >> 21;
+    s9 += carry8;
+    s8 -= carry8 * ((uint64_t) 1L << 21);
+    carry9 = s9 >> 21;
+    s10 += carry9;
+    s9 -= carry9 * ((uint64_t) 1L << 21);
+    carry10 = s10 >> 21;
+    s11 += carry10;
+    s10 -= carry10 * ((uint64_t) 1L << 21);
+
+    s[0]  = s0 >> 0;
+    s[1]  = s0 >> 8;
+    s[2]  = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
+    s[3]  = s1 >> 3;
+    s[4]  = s1 >> 11;
+    s[5]  = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
+    s[6]  = s2 >> 6;
+    s[7]  = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
+    s[8]  = s3 >> 1;
+    s[9]  = s3 >> 9;
+    s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
+    s[11] = s4 >> 4;
+    s[12] = s4 >> 12;
+    s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
+    s[14] = s5 >> 7;
+    s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
+    s[16] = s6 >> 2;
+    s[17] = s6 >> 10;
+    s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
+    s[19] = s7 >> 5;
+    s[20] = s7 >> 13;
+    s[21] = s8 >> 0;
+    s[22] = s8 >> 8;
+    s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
+    s[24] = s9 >> 3;
+    s[25] = s9 >> 11;
+    s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
+    s[27] = s10 >> 6;
+    s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
+    s[29] = s11 >> 1;
+    s[30] = s11 >> 9;
+    s[31] = s11 >> 17;
+}
+
+int
+sc25519_is_canonical(const unsigned char s[32])
+{
+    /* 2^252+27742317777372353535851937790883648493 */
+    static const unsigned char L[32] = {
+        0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
+        0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
+    };
+    unsigned char c = 0;
+    unsigned char n = 1;
+    unsigned int  i = 32;
+
+    do {
+        i--;
+        c |= ((s[i] - L[i]) >> 8) & n;
+        n &= ((s[i] ^ L[i]) - 1) >> 8;
+    } while (i != 0);
+
+    return (c != 0);
+}
+
+static void
+chi25519(fe25519 out, const fe25519 z)
+{
+    fe25519 t0, t1, t2, t3;
+    int     i;
+
+    fe25519_sq(t0, z);
+    fe25519_mul(t1, t0, z);
+    fe25519_sq(t0, t1);
+    fe25519_sq(t2, t0);
+    fe25519_sq(t2, t2);
+    fe25519_mul(t2, t2, t0);
+    fe25519_mul(t1, t2, z);
+    fe25519_sq(t2, t1);
+
+    for (i = 1; i < 5; i++) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 10; i++) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t2, t2, t1);
+    fe25519_sq(t3, t2);
+    for (i = 1; i < 20; i++) {
+        fe25519_sq(t3, t3);
+    }
+    fe25519_mul(t2, t3, t2);
+    fe25519_sq(t2, t2);
+    for (i = 1; i < 10; i++) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t2, t1);
+    for (i = 1; i < 50; i++) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t2, t2, t1);
+    fe25519_sq(t3, t2);
+    for (i = 1; i < 100; i++) {
+        fe25519_sq(t3, t3);
+    }
+    fe25519_mul(t2, t3, t2);
+    fe25519_sq(t2, t2);
+    for (i = 1; i < 50; i++) {
+        fe25519_sq(t2, t2);
+    }
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1);
+    for (i = 1; i < 4; i++) {
+        fe25519_sq(t1, t1);
+    }
+    fe25519_mul(out, t1, t0);
+}
+
+static void
+ge25519_elligator2(unsigned char s[32], const fe25519 r, const unsigned char x_sign)
+{
+    fe25519      e;
+    fe25519      negx;
+    fe25519      rr2;
+    fe25519      x, x2, x3;
+    ge25519_p3   p3;
+    ge25519_p1p1 p1;
+    ge25519_p2   p2;
+    unsigned int e_is_minus_1;
+
+    fe25519_sq2(rr2, r);
+    rr2[0]++;
+    fe25519_invert(rr2, rr2);
+    fe25519_mul(x, curve25519_A, rr2);
+    fe25519_neg(x, x);
+
+    fe25519_sq(x2, x);
+    fe25519_mul(x3, x, x2);
+    fe25519_add(e, x3, x);
+    fe25519_mul(x2, x2, curve25519_A);
+    fe25519_add(e, x2, e);
+
+    chi25519(e, e);
+
+    fe25519_tobytes(s, e);
+    e_is_minus_1 = s[1] & 1;
+    fe25519_neg(negx, x);
+    fe25519_cmov(x, negx, e_is_minus_1);
+    fe25519_0(x2);
+    fe25519_cmov(x2, curve25519_A, e_is_minus_1);
+    fe25519_sub(x, x, x2);
+
+    /* yed = (x-1)/(x+1) */
+    {
+        fe25519 one;
+        fe25519 x_plus_one;
+        fe25519 x_plus_one_inv;
+        fe25519 x_minus_one;
+        fe25519 yed;
+
+        fe25519_1(one);
+        fe25519_add(x_plus_one, x, one);
+        fe25519_sub(x_minus_one, x, one);
+        fe25519_invert(x_plus_one_inv, x_plus_one);
+        fe25519_mul(yed, x_minus_one, x_plus_one_inv);
+        fe25519_tobytes(s, yed);
+    }
+
+    /* recover x */
+    s[31] |= x_sign;
+    if (ge25519_frombytes(&p3, s) != 0) {
+        abort(); /* LCOV_EXCL_LINE */
+    }
+
+    /* multiply by the cofactor */
+    ge25519_p3_dbl(&p1, &p3);
+    ge25519_p1p1_to_p2(&p2, &p1);
+    ge25519_p2_dbl(&p1, &p2);
+    ge25519_p1p1_to_p2(&p2, &p1);
+    ge25519_p2_dbl(&p1, &p2);
+    ge25519_p1p1_to_p3(&p3, &p1);
+
+    ge25519_p3_tobytes(s, &p3);
+}
+
+void
+ge25519_from_uniform(unsigned char s[32], const unsigned char r[32])
+{
+    fe25519       r_fe;
+    unsigned char x_sign;
+
+    memcpy(s, r, 32);
+    x_sign = s[31] & 0x80;
+    s[31] &= 0x7f;
+    fe25519_frombytes(r_fe, s);
+    ge25519_elligator2(s, r_fe, x_sign);
+}
+
+void
+ge25519_from_hash(unsigned char s[32], const unsigned char h[64])
+{
+    unsigned char fl[32];
+    unsigned char gl[32];
+    fe25519       fe_f;
+    fe25519       fe_g;
+    size_t        i;
+    unsigned char x_sign;
+
+    x_sign = h[0] & 0x80;
+    for (i = 0; i < 32; i++) {
+        fl[i] = h[63 - i];
+        gl[i] = h[31 - i];
+    }
+    fl[31] &= 0x7f;
+    gl[31] &= 0x7f;
+    fe25519_frombytes(fe_f, fl);
+    fe25519_frombytes(fe_g, gl);
+    fe_f[0] += (h[32] >> 7) * 19;
+    for (i = 0; i < sizeof (fe25519) / sizeof fe_f[0]; i++) {
+        fe_f[i] += 38 * fe_g[i];
+    }
+    fe25519_reduce(fe_f, fe_f);
+    ge25519_elligator2(s, fe_f, x_sign);
+}
+
+/* Ristretto group */
+
+static int
+ristretto255_sqrt_ratio_m1(fe25519 x, const fe25519 u, const fe25519 v)
+{
+    fe25519 v3;
+    fe25519 vxx;
+    fe25519 m_root_check, p_root_check, f_root_check;
+    fe25519 x_sqrtm1;
+    int     has_m_root, has_p_root, has_f_root;
+
+    fe25519_sq(v3, v);
+    fe25519_mul(v3, v3, v); /* v3 = v^3 */
+    fe25519_sq(x, v3);
+    fe25519_mul(x, x, v);
+    fe25519_mul(x, x, u); /* x = uv^7 */
+
+    fe25519_pow22523(x, x); /* x = (uv^7)^((q-5)/8) */
+    fe25519_mul(x, x, v3);
+    fe25519_mul(x, x, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+    fe25519_sq(vxx, x);
+    fe25519_mul(vxx, vxx, v); /* vx^2 */
+    fe25519_sub(m_root_check, vxx, u); /* vx^2-u */
+    fe25519_add(p_root_check, vxx, u); /* vx^2+u */
+    fe25519_mul(f_root_check, u, sqrtm1); /* u*sqrt(-1) */
+    fe25519_add(f_root_check, vxx, f_root_check); /* vx^2+u*sqrt(-1) */
+    has_m_root = fe25519_iszero(m_root_check);
+    has_p_root = fe25519_iszero(p_root_check);
+    has_f_root = fe25519_iszero(f_root_check);
+    fe25519_mul(x_sqrtm1, x, sqrtm1); /* x*sqrt(-1) */
+
+    fe25519_cmov(x, x_sqrtm1, has_p_root | has_f_root);
+    fe25519_abs(x, x);
+
+    return has_m_root | has_p_root;
+}
+
+static int
+ristretto255_is_canonical(const unsigned char *s)
+{
+    unsigned char c;
+    unsigned char d;
+    unsigned int  i;
+
+    c = (s[31] & 0x7f) ^ 0x7f;
+    for (i = 30; i > 0; i--) {
+        c |= s[i] ^ 0xff;
+    }
+    c = (((unsigned int) c) - 1U) >> 8;
+    d = (0xed - 1U - (unsigned int) s[0]) >> 8;
+
+    return 1 - (((c & d) | s[0]) & 1);
+}
+
+int
+ristretto255_frombytes(ge25519_p3 *h, const unsigned char *s)
+{
+    fe25519 inv_sqrt;
+    fe25519 one;
+    fe25519 s_;
+    fe25519 ss;
+    fe25519 u1, u2;
+    fe25519 u1u1, u2u2;
+    fe25519 v;
+    fe25519 v_u2u2;
+    int     was_square;
+
+    if (ristretto255_is_canonical(s) == 0) {
+        return -1;
+    }
+    fe25519_frombytes(s_, s);
+    fe25519_sq(ss, s_);                /* ss = s^2 */
+
+    fe25519_1(u1);
+    fe25519_sub(u1, u1, ss);           /* u1 = 1-ss */
+    fe25519_sq(u1u1, u1);              /* u1u1 = u1^2 */
+
+    fe25519_1(u2);
+    fe25519_add(u2, u2, ss);           /* u2 = 1+ss */
+    fe25519_sq(u2u2, u2);              /* u2u2 = u2^2 */
+
+    fe25519_mul(v, d, u1u1);           /* v = d*u1^2 */
+    fe25519_neg(v, v);                 /* v = -d*u1^2 */
+    fe25519_sub(v, v, u2u2);           /* v = -(d*u1^2)-u2^2 */
+
+    fe25519_mul(v_u2u2, v, u2u2);      /* v_u2u2 = v*u2^2 */
+
+    fe25519_1(one);
+    was_square = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
+    fe25519_mul(h->X, inv_sqrt, u2);
+    fe25519_mul(h->Y, inv_sqrt, h->X);
+    fe25519_mul(h->Y, h->Y, v);
+
+    fe25519_mul(h->X, h->X, s_);
+    fe25519_add(h->X, h->X, h->X);
+    fe25519_abs(h->X, h->X);
+    fe25519_mul(h->Y, u1, h->Y);
+    fe25519_1(h->Z);
+    fe25519_mul(h->T, h->X, h->Y);
+
+    return - ((1 - was_square) |
+              fe25519_isnegative(h->T) | fe25519_iszero(h->Y));
+}
+
+void
+ristretto255_p3_tobytes(unsigned char *s, const ge25519_p3 *h)
+{
+    fe25519 den1, den2;
+    fe25519 den_inv;
+    fe25519 eden;
+    fe25519 inv_sqrt;
+    fe25519 ix, iy;
+    fe25519 one;
+    fe25519 s_;
+    fe25519 t_z_inv;
+    fe25519 u1, u2;
+    fe25519 u1_u2u2;
+    fe25519 x_, y_;
+    fe25519 x_z_inv;
+    fe25519 z_inv;
+    fe25519 zmy;
+    int     rotate;
+
+    fe25519_add(u1, h->Z, h->Y);       /* u1 = Z+Y */
+    fe25519_sub(zmy, h->Z, h->Y);      /* zmy = Z-Y */
+    fe25519_mul(u1, u1, zmy);          /* u1 = (Z+Y)*(Z-Y) */
+    fe25519_mul(u2, h->X, h->Y);       /* u2 = X*Y */
+
+    fe25519_sq(u1_u2u2, u2);           /* u1_u2u2 = u2^2 */
+    fe25519_mul(u1_u2u2, u1, u1_u2u2); /* u1_u2u2 = u1*u2^2 */
+
+    fe25519_1(one);
+    (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
+    fe25519_mul(den1, inv_sqrt, u1);   /* den1 = inv_sqrt*u1 */
+    fe25519_mul(den2, inv_sqrt, u2);   /* den2 = inv_sqrt*u2 */
+    fe25519_mul(z_inv, den1, den2);    /* z_inv = den1*den2 */
+    fe25519_mul(z_inv, z_inv, h->T);   /* z_inv = den1*den2*T */
+
+    fe25519_mul(ix, h->X, sqrtm1);     /* ix = X*sqrt(-1) */
+    fe25519_mul(iy, h->Y, sqrtm1);     /* iy = Y*sqrt(-1) */
+    fe25519_mul(eden, den1, invsqrtamd); /* eden = den1*sqrt(a-d) */
+
+    fe25519_mul(t_z_inv, h->T, z_inv); /* t_z_inv = T*z_inv */
+    rotate = fe25519_isnegative(t_z_inv);
+
+    fe25519_copy(x_, h->X);
+    fe25519_copy(y_, h->Y);
+    fe25519_copy(den_inv, den2);
+
+    fe25519_cmov(x_, iy, rotate);
+    fe25519_cmov(y_, ix, rotate);
+    fe25519_cmov(den_inv, eden, rotate);
+
+    fe25519_mul(x_z_inv, x_, z_inv);
+    fe25519_cneg(y_, y_, fe25519_isnegative(x_z_inv));
+
+    fe25519_sub(s_, h->Z, y_);
+    fe25519_mul(s_, den_inv, s_);
+    fe25519_abs(s_, s_);
+    fe25519_tobytes(s, s_);
+}
+
+static void
+ristretto255_elligator(ge25519_p3 *p, const fe25519 t)
+{
+    fe25519 c;
+    fe25519 n;
+    fe25519 one;
+    fe25519 r;
+    fe25519 rpd;
+    fe25519 s, s_prime;
+    fe25519 ss;
+    fe25519 u, v;
+    fe25519 w0, w1, w2, w3;
+    int     wasnt_square;
+
+    fe25519_1(one);
+    fe25519_sq(r, t);                  /* r = t^2 */
+    fe25519_mul(r, sqrtm1, r);         /* r = sqrt(-1)*t^2 */
+    fe25519_add(u, r, one);            /* u = r+1 */
+    fe25519_mul(u, u, onemsqd);        /* u = (r+1)*(1-d^2) */
+    fe25519_1(c);
+    fe25519_neg(c, c);                 /* c = -1 */
+    fe25519_add(rpd, r, d);            /* rpd = r*d */
+    fe25519_mul(v, r, d);              /* v = r*d */
+    fe25519_sub(v, c, v);              /* v = c-r*d */
+    fe25519_mul(v, v, rpd);            /* v = (c-r*d)*(r+d) */
+
+    wasnt_square = 1 - ristretto255_sqrt_ratio_m1(s, u, v);
+    fe25519_mul(s_prime, s, t);
+    fe25519_abs(s_prime, s_prime);
+    fe25519_neg(s_prime, s_prime);     /* s_prime = -|s*t| */
+    fe25519_cmov(s, s_prime, wasnt_square);
+    fe25519_cmov(c, r, wasnt_square);
+
+    fe25519_sub(n, r, one);            /* n = r-1 */
+    fe25519_mul(n, n, c);              /* n = c*(r-1) */
+    fe25519_mul(n, n, sqdmone);        /* n = c*(r-1)*(d-1)^2 */
+    fe25519_sub(n, n, v);              /* n =  c*(r-1)*(d-1)^2-v */
+
+    fe25519_add(w0, s, s);             /* w0 = 2s */
+    fe25519_mul(w0, w0, v);            /* w0 = 2s*v */
+    fe25519_mul(w1, n, sqrtadm1);      /* w1 = n*sqrt(ad-1) */
+    fe25519_sq(ss, s);                 /* ss = s^2 */
+    fe25519_sub(w2, one, ss);          /* w2 = 1-s^2 */
+    fe25519_add(w3, one, ss);          /* w3 = 1+s^2 */
+
+    fe25519_mul(p->X, w0, w3);
+    fe25519_mul(p->Y, w2, w1);
+    fe25519_mul(p->Z, w1, w3);
+    fe25519_mul(p->T, w0, w2);
+}
+
+void
+ristretto255_from_hash(unsigned char s[32], const unsigned char h[64])
+{
+    fe25519        r0, r1;
+    ge25519_cached p1_cached;
+    ge25519_p1p1   p_p1p1;
+    ge25519_p3     p0, p1;
+    ge25519_p3     p;
+
+    fe25519_frombytes(r0, h);
+    fe25519_frombytes(r1, h + 32);
+    ristretto255_elligator(&p0, r0);
+    ristretto255_elligator(&p1, r1);
+    ge25519_p3_to_cached(&p1_cached, &p1);
+    ge25519_add(&p_p1p1, &p0, &p1_cached);
+    ge25519_p1p1_to_p3(&p, &p_p1p1);
+    ristretto255_p3_tobytes(s, &p);
+}

+ 1344 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/base.h

@@ -0,0 +1,1344 @@
+{ /* 0/31 */
+  {
+    { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 },
+    { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 },
+    { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }
+  },
+  {
+    { -12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303 },
+    { -21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081 },
+    { 26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697 }
+  },
+  {
+    { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 },
+    { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 },
+    { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }
+  },
+  {
+    { -17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540 },
+    { 23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397 },
+    { 7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325 }
+  },
+  {
+    { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 },
+    { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 },
+    { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }
+  },
+  {
+    { -15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777 },
+    { -8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737 },
+    { -18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652 }
+  },
+  {
+    { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 },
+    { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 },
+    { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }
+  },
+  {
+    { 14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726 },
+    { -7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955 },
+    { 27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425 }
+  }
+},
+{ /* 1/31 */
+  {
+    { -13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171 },
+    { 27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510 },
+    { 17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660 }
+  },
+  {
+    { -10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639 },
+    { 29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963 },
+    { 5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950 }
+  },
+  {
+    { -27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568 },
+    { 12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335 },
+    { 25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628 }
+  },
+  {
+    { -26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007 },
+    { -2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772 },
+    { -22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653 }
+  },
+  {
+    { 2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567 },
+    { 13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686 },
+    { 21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372 }
+  },
+  {
+    { -13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887 },
+    { -23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954 },
+    { -29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953 }
+  },
+  {
+    { 24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833 },
+    { -16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532 },
+    { -22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876 }
+  },
+  {
+    { 2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268 },
+    { 33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214 },
+    { 1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038 }
+  }
+},
+{ /* 2/31 */
+  {
+    { 6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800 },
+    { 4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645 },
+    { -4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664 }
+  },
+  {
+    { 1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933 },
+    { -25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182 },
+    { -17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222 }
+  },
+  {
+    { -18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991 },
+    { 20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880 },
+    { 9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092 }
+  },
+  {
+    { -16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295 },
+    { 19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788 },
+    { 8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553 }
+  },
+  {
+    { -15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026 },
+    { 11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347 },
+    { -18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033 }
+  },
+  {
+    { -23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395 },
+    { -27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278 },
+    { 1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890 }
+  },
+  {
+    { 32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995 },
+    { -30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596 },
+    { -11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891 }
+  },
+  {
+    { 31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060 },
+    { 11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608 },
+    { -20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606 }
+  }
+},
+{ /* 3/31 */
+  {
+    { 7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389 },
+    { -19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016 },
+    { -11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341 }
+  },
+  {
+    { -22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505 },
+    { 14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553 },
+    { -28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655 }
+  },
+  {
+    { 15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220 },
+    { 12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631 },
+    { -4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099 }
+  },
+  {
+    { 26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556 },
+    { 14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749 },
+    { 236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930 }
+  },
+  {
+    { 1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391 },
+    { 5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253 },
+    { 20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066 }
+  },
+  {
+    { 24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958 },
+    { -11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082 },
+    { -28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383 }
+  },
+  {
+    { -30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521 },
+    { -11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807 },
+    { 23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948 }
+  },
+  {
+    { 9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134 },
+    { -32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455 },
+    { 27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629 }
+  }
+},
+{ /* 4/31 */
+  {
+    { -8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069 },
+    { -32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746 },
+    { 24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919 }
+  },
+  {
+    { 11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837 },
+    { 8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906 },
+    { -28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771 }
+  },
+  {
+    { -25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817 },
+    { 10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098 },
+    { 10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409 }
+  },
+  {
+    { -12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504 },
+    { -26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727 },
+    { 28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420 }
+  },
+  {
+    { -32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003 },
+    { -1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605 },
+    { -30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384 }
+  },
+  {
+    { -26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701 },
+    { -23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683 },
+    { 29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708 }
+  },
+  {
+    { -3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563 },
+    { -19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260 },
+    { -5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387 }
+  },
+  {
+    { -19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672 },
+    { 23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686 },
+    { -24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665 }
+  }
+},
+{ /* 5/31 */
+  {
+    { 11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182 },
+    { -31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277 },
+    { 14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628 }
+  },
+  {
+    { -4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474 },
+    { -26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539 },
+    { -25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822 }
+  },
+  {
+    { -10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970 },
+    { 19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756 },
+    { -24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508 }
+  },
+  {
+    { -26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683 },
+    { -10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655 },
+    { -20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158 }
+  },
+  {
+    { -4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125 },
+    { -15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839 },
+    { -20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664 }
+  },
+  {
+    { 27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294 },
+    { -18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899 },
+    { -11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070 }
+  },
+  {
+    { 3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294 },
+    { -15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949 },
+    { -21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083 }
+  },
+  {
+    { 31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420 },
+    { -5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940 },
+    { 29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396 }
+  }
+},
+{ /* 6/31 */
+  {
+    { -12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567 },
+    { 20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127 },
+    { -16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294 }
+  },
+  {
+    { -12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887 },
+    { 22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964 },
+    { 16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195 }
+  },
+  {
+    { 9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244 },
+    { 24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999 },
+    { -1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762 }
+  },
+  {
+    { -18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274 },
+    { -33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236 },
+    { -16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605 }
+  },
+  {
+    { -13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761 },
+    { -22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884 },
+    { -6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482 }
+  },
+  {
+    { -24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638 },
+    { -11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490 },
+    { -32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170 }
+  },
+  {
+    { 5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736 },
+    { 10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124 },
+    { -17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392 }
+  },
+  {
+    { 8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029 },
+    { 6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048 },
+    { 28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958 }
+  }
+},
+{ /* 7/31 */
+  {
+    { 24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593 },
+    { 26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071 },
+    { -11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692 }
+  },
+  {
+    { 11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687 },
+    { -160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441 },
+    { -20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001 }
+  },
+  {
+    { -938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460 },
+    { -19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007 },
+    { -21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762 }
+  },
+  {
+    { 15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005 },
+    { -9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674 },
+    { 4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035 }
+  },
+  {
+    { 7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590 },
+    { -2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957 },
+    { -30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812 }
+  },
+  {
+    { 33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740 },
+    { -18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122 },
+    { -27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158 }
+  },
+  {
+    { 8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885 },
+    { 26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140 },
+    { 19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857 }
+  },
+  {
+    { 801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155 },
+    { 19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260 },
+    { 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483 }
+  }
+},
+{ /* 8/31 */
+  {
+    { -3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677 },
+    { 32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815 },
+    { 22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751 }
+  },
+  {
+    { -16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203 },
+    { -11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208 },
+    { 1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230 }
+  },
+  {
+    { 16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850 },
+    { -21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389 },
+    { -9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968 }
+  },
+  {
+    { -11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689 },
+    { 14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880 },
+    { 5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304 }
+  },
+  {
+    { 30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632 },
+    { -3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412 },
+    { 20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566 }
+  },
+  {
+    { -20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038 },
+    { -26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232 },
+    { -1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943 }
+  },
+  {
+    { 17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856 },
+    { 23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738 },
+    { 15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971 }
+  },
+  {
+    { -27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718 },
+    { -13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697 },
+    { -11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883 }
+  }
+},
+{ /* 9/31 */
+  {
+    { 5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912 },
+    { -26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358 },
+    { 3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849 }
+  },
+  {
+    { 29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307 },
+    { -14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977 },
+    { -6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335 }
+  },
+  {
+    { -29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644 },
+    { -22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616 },
+    { -27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735 }
+  },
+  {
+    { -21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099 },
+    { 29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341 },
+    { -936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336 }
+  },
+  {
+    { -23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646 },
+    { 31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425 },
+    { -17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388 }
+  },
+  {
+    { -31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743 },
+    { -16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822 },
+    { -8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462 }
+  },
+  {
+    { 18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985 },
+    { 9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702 },
+    { -22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797 }
+  },
+  {
+    { 21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293 },
+    { 27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100 },
+    { 19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688 }
+  }
+},
+{ /* 10/31 */
+  {
+    { 12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186 },
+    { 2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610 },
+    { -2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707 }
+  },
+  {
+    { 7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220 },
+    { 915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025 },
+    { 32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044 }
+  },
+  {
+    { 32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992 },
+    { -4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027 },
+    { 21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197 }
+  },
+  {
+    { 8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901 },
+    { 31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952 },
+    { 19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878 }
+  },
+  {
+    { -28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390 },
+    { 32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730 },
+    { 2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730 }
+  },
+  {
+    { -19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180 },
+    { -30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272 },
+    { -15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715 }
+  },
+  {
+    { -22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970 },
+    { -31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772 },
+    { -17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865 }
+  },
+  {
+    { 15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750 },
+    { 20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373 },
+    { 32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348 }
+  }
+},
+{ /* 11/31 */
+  {
+    { 9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144 },
+    { -22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195 },
+    { 5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086 }
+  },
+  {
+    { -13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684 },
+    { -8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518 },
+    { -2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233 }
+  },
+  {
+    { -5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793 },
+    { -2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794 },
+    { 580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435 }
+  },
+  {
+    { 23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921 },
+    { 13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518 },
+    { 2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563 }
+  },
+  {
+    { 14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278 },
+    { -27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024 },
+    { 4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030 }
+  },
+  {
+    { 10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783 },
+    { 27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717 },
+    { 6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844 }
+  },
+  {
+    { 14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333 },
+    { 16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048 },
+    { 22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760 }
+  },
+  {
+    { -4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760 },
+    { -15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757 },
+    { -2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112 }
+  }
+},
+{ /* 12/31 */
+  {
+    { -19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468 },
+    { 3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184 },
+    { 10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289 }
+  },
+  {
+    { 15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066 },
+    { 24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882 },
+    { 13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226 }
+  },
+  {
+    { 16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101 },
+    { 29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279 },
+    { -6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811 }
+  },
+  {
+    { 27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709 },
+    { 20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714 },
+    { -2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121 }
+  },
+  {
+    { 9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464 },
+    { 12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847 },
+    { 13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400 }
+  },
+  {
+    { 4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414 },
+    { -15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158 },
+    { 17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045 }
+  },
+  {
+    { -461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415 },
+    { -5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459 },
+    { -31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079 }
+  },
+  {
+    { 21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412 },
+    { -20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743 },
+    { -14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836 }
+  }
+},
+{ /* 13/31 */
+  {
+    { 12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022 },
+    { 18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429 },
+    { -6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065 }
+  },
+  {
+    { 30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861 },
+    { 10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000 },
+    { -33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101 }
+  },
+  {
+    { 32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815 },
+    { 29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642 },
+    { 10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966 }
+  },
+  {
+    { 25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574 },
+    { -21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742 },
+    { -18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689 }
+  },
+  {
+    { 12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020 },
+    { -10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772 },
+    { 3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982 }
+  },
+  {
+    { -14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953 },
+    { -16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218 },
+    { -17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265 }
+  },
+  {
+    { 29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073 },
+    { -3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325 },
+    { -11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798 }
+  },
+  {
+    { -4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870 },
+    { -7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863 },
+    { -13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927 }
+  }
+},
+{ /* 14/31 */
+  {
+    { -2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267 },
+    { -9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663 },
+    { 22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862 }
+  },
+  {
+    { -25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673 },
+    { 15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943 },
+    { 15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020 }
+  },
+  {
+    { -4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238 },
+    { 11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064 },
+    { 14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795 }
+  },
+  {
+    { 15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052 },
+    { -10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904 },
+    { 29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531 }
+  },
+  {
+    { -13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979 },
+    { -5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841 },
+    { 10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431 }
+  },
+  {
+    { 10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324 },
+    { -31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940 },
+    { 10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320 }
+  },
+  {
+    { -15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184 },
+    { 14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114 },
+    { 30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878 }
+  },
+  {
+    { 12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784 },
+    { -2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091 },
+    { -16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585 }
+  }
+},
+{ /* 15/31 */
+  {
+    { -8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208 },
+    { 10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864 },
+    { 17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661 }
+  },
+  {
+    { 7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233 },
+    { 26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212 },
+    { -12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525 }
+  },
+  {
+    { -24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068 },
+    { 9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397 },
+    { -8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988 }
+  },
+  {
+    { 5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889 },
+    { 32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038 },
+    { 14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697 }
+  },
+  {
+    { 20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875 },
+    { -25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905 },
+    { -25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656 }
+  },
+  {
+    { 11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818 },
+    { 27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714 },
+    { 10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203 }
+  },
+  {
+    { 20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931 },
+    { -30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024 },
+    { -23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084 }
+  },
+  {
+    { -1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204 },
+    { 20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817 },
+    { 27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667 }
+  }
+},
+{ /* 16/31 */
+  {
+    { 11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504 },
+    { -12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768 },
+    { -19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255 }
+  },
+  {
+    { 6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790 },
+    { 1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438 },
+    { -22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333 }
+  },
+  {
+    { 17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971 },
+    { 31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905 },
+    { 29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409 }
+  },
+  {
+    { 12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409 },
+    { 6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499 },
+    { -8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363 }
+  },
+  {
+    { 28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664 },
+    { -11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324 },
+    { -21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940 }
+  },
+  {
+    { 13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990 },
+    { -17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914 },
+    { -25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290 }
+  },
+  {
+    { 24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257 },
+    { -6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433 },
+    { -16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236 }
+  },
+  {
+    { -12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045 },
+    { 11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093 },
+    { -1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347 }
+  }
+},
+{ /* 17/31 */
+  {
+    { -28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191 },
+    { -15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507 },
+    { -12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906 }
+  },
+  {
+    { 3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018 },
+    { -16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109 },
+    { -23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926 }
+  },
+  {
+    { -24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528 },
+    { 8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625 },
+    { -32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286 }
+  },
+  {
+    { 2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033 },
+    { 27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866 },
+    { 21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896 }
+  },
+  {
+    { 30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075 },
+    { 26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347 },
+    { -22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437 }
+  },
+  {
+    { -5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165 },
+    { -18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588 },
+    { -32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193 }
+  },
+  {
+    { -19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017 },
+    { -28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883 },
+    { 21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961 }
+  },
+  {
+    { 8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043 },
+    { 29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663 },
+    { -20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362 }
+  }
+},
+{ /* 18/31 */
+  {
+    { -33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860 },
+    { 2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466 },
+    { -24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063 }
+  },
+  {
+    { -26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997 },
+    { -1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295 },
+    { -13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369 }
+  },
+  {
+    { 9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385 },
+    { 18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109 },
+    { 2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906 }
+  },
+  {
+    { 4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424 },
+    { -19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185 },
+    { 7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962 }
+  },
+  {
+    { -7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325 },
+    { 10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593 },
+    { 696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404 }
+  },
+  {
+    { -11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644 },
+    { 17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801 },
+    { 26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804 }
+  },
+  {
+    { -31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884 },
+    { -586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577 },
+    { -9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849 }
+  },
+  {
+    { 32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473 },
+    { -8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644 },
+    { -2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319 }
+  }
+},
+{ /* 19/31 */
+  {
+    { -11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599 },
+    { -9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768 },
+    { -27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084 }
+  },
+  {
+    { -27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328 },
+    { -15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369 },
+    { 20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920 }
+  },
+  {
+    { 12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815 },
+    { -32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025 },
+    { -21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397 }
+  },
+  {
+    { -20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448 },
+    { 6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981 },
+    { 30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165 }
+  },
+  {
+    { 32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501 },
+    { 17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073 },
+    { -1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861 }
+  },
+  {
+    { 14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845 },
+    { -1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211 },
+    { 18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870 }
+  },
+  {
+    { 10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096 },
+    { 33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803 },
+    { -32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168 }
+  },
+  {
+    { 30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965 },
+    { -14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505 },
+    { 18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598 }
+  }
+},
+{ /* 20/31 */
+  {
+    { 5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782 },
+    { 5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900 },
+    { -31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479 }
+  },
+  {
+    { -12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208 },
+    { 8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232 },
+    { 17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719 }
+  },
+  {
+    { 16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271 },
+    { -4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326 },
+    { -8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132 }
+  },
+  {
+    { 14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300 },
+    { 8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570 },
+    { 15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670 }
+  },
+  {
+    { -2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994 },
+    { -12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913 },
+    { 31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317 }
+  },
+  {
+    { -25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730 },
+    { 842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096 },
+    { -4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078 }
+  },
+  {
+    { -15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411 },
+    { -19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905 },
+    { -9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654 }
+  },
+  {
+    { -28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870 },
+    { -23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498 },
+    { 12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579 }
+  }
+},
+{ /* 21/31 */
+  {
+    { 14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677 },
+    { 10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647 },
+    { -2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743 }
+  },
+  {
+    { -25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468 },
+    { 21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375 },
+    { -25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155 }
+  },
+  {
+    { 6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725 },
+    { -12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612 },
+    { -10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943 }
+  },
+  {
+    { -30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944 },
+    { 30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928 },
+    { 9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406 }
+  },
+  {
+    { 22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139 },
+    { -8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963 },
+    { -31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693 }
+  },
+  {
+    { 1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734 },
+    { -448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680 },
+    { -24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410 }
+  },
+  {
+    { -9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931 },
+    { -16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654 },
+    { 22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710 }
+  },
+  {
+    { 29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180 },
+    { -26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684 },
+    { -10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895 }
+  }
+},
+{ /* 22/31 */
+  {
+    { 22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501 },
+    { -11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413 },
+    { 6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880 }
+  },
+  {
+    { -8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874 },
+    { 22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962 },
+    { -7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899 }
+  },
+  {
+    { 21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152 },
+    { 9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063 },
+    { 7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080 }
+  },
+  {
+    { -9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146 },
+    { -17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183 },
+    { -19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133 }
+  },
+  {
+    { -32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421 },
+    { -3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622 },
+    { -4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197 }
+  },
+  {
+    { 2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663 },
+    { 31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753 },
+    { 4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755 }
+  },
+  {
+    { -9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862 },
+    { -26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118 },
+    { 26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171 }
+  },
+  {
+    { 15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380 },
+    { 16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824 },
+    { 28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270 }
+  }
+},
+{ /* 23/31 */
+  {
+    { -817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438 },
+    { -31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584 },
+    { -594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562 }
+  },
+  {
+    { 30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471 },
+    { 18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610 },
+    { 19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269 }
+  },
+  {
+    { -30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650 },
+    { 14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369 },
+    { 19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461 }
+  },
+  {
+    { 30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462 },
+    { -5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793 },
+    { -2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218 }
+  },
+  {
+    { -24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226 },
+    { 18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019 },
+    { -15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037 }
+  },
+  {
+    { 31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171 },
+    { -17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132 },
+    { -28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841 }
+  },
+  {
+    { 21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181 },
+    { -33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210 },
+    { -1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040 }
+  },
+  {
+    { 3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935 },
+    { 24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105 },
+    { -28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814 }
+  }
+},
+{ /* 24/31 */
+  {
+    { 793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852 },
+    { 5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581 },
+    { -4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646 }
+  },
+  {
+    { 10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844 },
+    { 10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025 },
+    { 27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453 }
+  },
+  {
+    { -23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068 },
+    { 4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192 },
+    { -17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921 }
+  },
+  {
+    { -9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259 },
+    { -12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426 },
+    { -5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072 }
+  },
+  {
+    { -17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305 },
+    { 13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832 },
+    { 28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943 }
+  },
+  {
+    { -16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011 },
+    { 24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447 },
+    { 17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494 }
+  },
+  {
+    { -28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245 },
+    { -20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859 },
+    { 28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915 }
+  },
+  {
+    { 16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707 },
+    { 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848 },
+    { -11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224 }
+  }
+},
+{ /* 25/31 */
+  {
+    { -25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391 },
+    { 15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215 },
+    { -23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101 }
+  },
+  {
+    { 23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713 },
+    { 21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849 },
+    { -7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930 }
+  },
+  {
+    { -29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940 },
+    { -21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031 },
+    { -17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404 }
+  },
+  {
+    { -25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243 },
+    { -23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116 },
+    { -24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525 }
+  },
+  {
+    { -23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509 },
+    { -10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883 },
+    { 15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865 }
+  },
+  {
+    { -3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660 },
+    { 4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273 },
+    { -28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138 }
+  },
+  {
+    { -25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560 },
+    { -10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135 },
+    { 2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941 }
+  },
+  {
+    { -4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739 },
+    { 18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756 },
+    { -30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819 }
+  }
+},
+{ /* 26/31 */
+  {
+    { -6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347 },
+    { -27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028 },
+    { 21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075 }
+  },
+  {
+    { 16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799 },
+    { -2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609 },
+    { -25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817 }
+  },
+  {
+    { -23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989 },
+    { -30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523 },
+    { 4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278 }
+  },
+  {
+    { 31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045 },
+    { 19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377 },
+    { 24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480 }
+  },
+  {
+    { 17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016 },
+    { 510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426 },
+    { 18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525 }
+  },
+  {
+    { 13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396 },
+    { 9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080 },
+    { 12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892 }
+  },
+  {
+    { 15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275 },
+    { 11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074 },
+    { 20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140 }
+  },
+  {
+    { -16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717 },
+    { -1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101 },
+    { 24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127 }
+  }
+},
+{ /* 27/31 */
+  {
+    { -12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632 },
+    { -26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415 },
+    { -31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160 }
+  },
+  {
+    { 31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876 },
+    { 22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625 },
+    { -15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478 }
+  },
+  {
+    { 27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164 },
+    { 26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595 },
+    { -7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248 }
+  },
+  {
+    { -16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858 },
+    { 15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193 },
+    { 8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184 }
+  },
+  {
+    { -18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942 },
+    { -1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635 },
+    { 21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948 }
+  },
+  {
+    { 11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935 },
+    { -25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415 },
+    { -15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416 }
+  },
+  {
+    { -7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018 },
+    { 4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778 },
+    { 366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659 }
+  },
+  {
+    { -24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385 },
+    { 18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503 },
+    { 476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329 }
+  }
+},
+{ /* 28/31 */
+  {
+    { 20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056 },
+    { -13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838 },
+    { 24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948 }
+  },
+  {
+    { -3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691 },
+    { -15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118 },
+    { -23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517 }
+  },
+  {
+    { -20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269 },
+    { -6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904 },
+    { -23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589 }
+  },
+  {
+    { -28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193 },
+    { -7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910 },
+    { -30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930 }
+  },
+  {
+    { -7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667 },
+    { 25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481 },
+    { -9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876 }
+  },
+  {
+    { 22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640 },
+    { -8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278 },
+    { -21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112 }
+  },
+  {
+    { 26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272 },
+    { 17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012 },
+    { -10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221 }
+  },
+  {
+    { 30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046 },
+    { 13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345 },
+    { -19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310 }
+  }
+},
+{ /* 29/31 */
+  {
+    { 19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937 },
+    { 31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636 },
+    { -9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008 }
+  },
+  {
+    { -2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429 },
+    { -15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576 },
+    { 31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066 }
+  },
+  {
+    { -9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490 },
+    { -12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104 },
+    { 33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053 }
+  },
+  {
+    { 31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275 },
+    { -20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511 },
+    { 22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095 }
+  },
+  {
+    { -28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439 },
+    { 23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939 },
+    { -23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424 }
+  },
+  {
+    { 2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310 },
+    { 3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608 },
+    { -32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079 }
+  },
+  {
+    { -23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101 },
+    { 21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418 },
+    { 18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576 }
+  },
+  {
+    { 30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356 },
+    { 9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996 },
+    { -26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099 }
+  }
+},
+{ /* 30/31 */
+  {
+    { -26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728 },
+    { -13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658 },
+    { -10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242 }
+  },
+  {
+    { -21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001 },
+    { -4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766 },
+    { 18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373 }
+  },
+  {
+    { 26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458 },
+    { -17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628 },
+    { -13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657 }
+  },
+  {
+    { -23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062 },
+    { 25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616 },
+    { 31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014 }
+  },
+  {
+    { 24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383 },
+    { -25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814 },
+    { -20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718 }
+  },
+  {
+    { 30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417 },
+    { 2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222 },
+    { 33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444 }
+  },
+  {
+    { -20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597 },
+    { 23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970 },
+    { 1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799 }
+  },
+  {
+    { -5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647 },
+    { 13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511 },
+    { -29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032 }
+  }
+},
+{ /* 31/31 */
+  {
+    { 9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834 },
+    { -23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461 },
+    { 29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062 }
+  },
+  {
+    { -25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516 },
+    { -20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547 },
+    { -24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240 }
+  },
+  {
+    { -17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038 },
+    { -33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741 },
+    { 16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103 }
+  },
+  {
+    { -19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747 },
+    { -1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323 },
+    { 31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016 }
+  },
+  {
+    { -14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373 },
+    { 15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228 },
+    { -2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141 }
+  },
+  {
+    { 16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399 },
+    { 11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831 },
+    { -185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376 }
+  },
+  {
+    { -32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313 },
+    { -18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958 },
+    { -6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577 }
+  },
+  {
+    { -22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743 },
+    { 29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684 },
+    { -20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476 }
+  }
+}

+ 40 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/base2.h

@@ -0,0 +1,40 @@
+{
+  { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 },
+  { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 },
+  { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }
+},
+{
+  { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 },
+  { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 },
+  { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }
+},
+{
+  { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 },
+  { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 },
+  { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }
+},
+{
+  { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 },
+  { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 },
+  { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }
+},
+{
+  { -22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877 },
+  { -6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951 },
+  { 4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784 }
+},
+{
+  { -25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436 },
+  { 25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918 },
+  { 23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877 }
+},
+{
+  { -33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800 },
+  { -25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305 },
+  { -13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300 }
+},
+{
+  { -3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876 },
+  { -24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619 },
+  { -3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683 }
+}

+ 40 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/constants.h

@@ -0,0 +1,40 @@
+/* 37095705934669439343138083508754565189542113879843219016388785533085940283555 */
+static const fe25519 d = {
+    -10913610, 13857413, -15372611, 6949391,   114729, -8787816, -6275908, -3247719, -18696448, -12055116
+};
+
+/* 2 * d =
+ * 16295367250680780974490674513165176452449235426866156013048779062215315747161
+ */
+static const fe25519 d2 = {
+    -21827239, -5839606,  -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 };
+
+/* sqrt(-1) */
+static const fe25519 sqrtm1 = {
+    -32595792, -7943725,  9377950,  3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
+};
+
+/* A = 486662 */
+static const fe25519 curve25519_A = {
+    486662, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* sqrt(ad - 1) with a = -1 (mod p) */
+static const fe25519 sqrtadm1 = {
+    24849947, -153582, -23613485, 6347715, -21072328, -667138, -25271143, -15367704, -870347, 14525639
+};
+
+/* 1 / sqrt(a - d) */
+static const fe25519 invsqrtamd = {
+    6111485, 4156064, -27798727, 12243468, -25904040, 120897, 20826367, -7060776, 6093568, -1986012
+};
+
+/* 1 - d ^ 2 */
+static const fe25519 onemsqd = {
+    6275446, -16617371, -22938544, -3773710, 11667077, 7397348, -27922721, 1766195, -24433858, 672203
+};
+
+/* (d - 1) ^ 2 */
+static const fe25519 sqdmone = {
+    15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402
+};

+ 220 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_25_5/fe.h

@@ -0,0 +1,220 @@
+/*
+ Ignores top bit of h.
+ */
+
+void
+fe25519_frombytes(fe25519 h, const unsigned char *s)
+{
+    int64_t h0 = load_4(s);
+    int64_t h1 = load_3(s + 4) << 6;
+    int64_t h2 = load_3(s + 7) << 5;
+    int64_t h3 = load_3(s + 10) << 3;
+    int64_t h4 = load_3(s + 13) << 2;
+    int64_t h5 = load_4(s + 16);
+    int64_t h6 = load_3(s + 20) << 7;
+    int64_t h7 = load_3(s + 23) << 5;
+    int64_t h8 = load_3(s + 26) << 4;
+    int64_t h9 = (load_3(s + 29) & 8388607) << 2;
+
+    int64_t carry0;
+    int64_t carry1;
+    int64_t carry2;
+    int64_t carry3;
+    int64_t carry4;
+    int64_t carry5;
+    int64_t carry6;
+    int64_t carry7;
+    int64_t carry8;
+    int64_t carry9;
+
+    carry9 = (h9 + (int64_t)(1L << 24)) >> 25;
+    h0 += carry9 * 19;
+    h9 -= carry9 * ((uint64_t) 1L << 25);
+    carry1 = (h1 + (int64_t)(1L << 24)) >> 25;
+    h2 += carry1;
+    h1 -= carry1 * ((uint64_t) 1L << 25);
+    carry3 = (h3 + (int64_t)(1L << 24)) >> 25;
+    h4 += carry3;
+    h3 -= carry3 * ((uint64_t) 1L << 25);
+    carry5 = (h5 + (int64_t)(1L << 24)) >> 25;
+    h6 += carry5;
+    h5 -= carry5 * ((uint64_t) 1L << 25);
+    carry7 = (h7 + (int64_t)(1L << 24)) >> 25;
+    h8 += carry7;
+    h7 -= carry7 * ((uint64_t) 1L << 25);
+
+    carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+    h1 += carry0;
+    h0 -= carry0 * ((uint64_t) 1L << 26);
+    carry2 = (h2 + (int64_t)(1L << 25)) >> 26;
+    h3 += carry2;
+    h2 -= carry2 * ((uint64_t) 1L << 26);
+    carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+    h5 += carry4;
+    h4 -= carry4 * ((uint64_t) 1L << 26);
+    carry6 = (h6 + (int64_t)(1L << 25)) >> 26;
+    h7 += carry6;
+    h6 -= carry6 * ((uint64_t) 1L << 26);
+    carry8 = (h8 + (int64_t)(1L << 25)) >> 26;
+    h9 += carry8;
+    h8 -= carry8 * ((uint64_t) 1L << 26);
+
+    h[0] = (int32_t) h0;
+    h[1] = (int32_t) h1;
+    h[2] = (int32_t) h2;
+    h[3] = (int32_t) h3;
+    h[4] = (int32_t) h4;
+    h[5] = (int32_t) h5;
+    h[6] = (int32_t) h6;
+    h[7] = (int32_t) h7;
+    h[8] = (int32_t) h8;
+    h[9] = (int32_t) h9;
+}
+
+/*
+ Preconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+
+ Write p=2^255-19; q=floor(h/p).
+ Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+
+ Proof:
+ Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+ Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
+
+ Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+ Then 0<y<1.
+
+ Write r=h-pq.
+ Have 0<=r<=p-1=2^255-20.
+ Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+
+ Write x=r+19(2^-255)r+y.
+ Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+
+ Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+ so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+*/
+
+static void
+fe25519_reduce(fe25519 h, const fe25519 f)
+{
+    int32_t h0 = f[0];
+    int32_t h1 = f[1];
+    int32_t h2 = f[2];
+    int32_t h3 = f[3];
+    int32_t h4 = f[4];
+    int32_t h5 = f[5];
+    int32_t h6 = f[6];
+    int32_t h7 = f[7];
+    int32_t h8 = f[8];
+    int32_t h9 = f[9];
+
+    int32_t q;
+    int32_t carry0, carry1, carry2, carry3, carry4, carry5, carry6, carry7, carry8, carry9;
+
+    q = (19 * h9 + ((uint32_t) 1L << 24)) >> 25;
+    q = (h0 + q) >> 26;
+    q = (h1 + q) >> 25;
+    q = (h2 + q) >> 26;
+    q = (h3 + q) >> 25;
+    q = (h4 + q) >> 26;
+    q = (h5 + q) >> 25;
+    q = (h6 + q) >> 26;
+    q = (h7 + q) >> 25;
+    q = (h8 + q) >> 26;
+    q = (h9 + q) >> 25;
+
+    /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
+    h0 += 19 * q;
+    /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
+
+    carry0 = h0 >> 26;
+    h1 += carry0;
+    h0 -= carry0 * ((uint32_t) 1L << 26);
+    carry1 = h1 >> 25;
+    h2 += carry1;
+    h1 -= carry1 * ((uint32_t) 1L << 25);
+    carry2 = h2 >> 26;
+    h3 += carry2;
+    h2 -= carry2 * ((uint32_t) 1L << 26);
+    carry3 = h3 >> 25;
+    h4 += carry3;
+    h3 -= carry3 * ((uint32_t) 1L << 25);
+    carry4 = h4 >> 26;
+    h5 += carry4;
+    h4 -= carry4 * ((uint32_t) 1L << 26);
+    carry5 = h5 >> 25;
+    h6 += carry5;
+    h5 -= carry5 * ((uint32_t) 1L << 25);
+    carry6 = h6 >> 26;
+    h7 += carry6;
+    h6 -= carry6 * ((uint32_t) 1L << 26);
+    carry7 = h7 >> 25;
+    h8 += carry7;
+    h7 -= carry7 * ((uint32_t) 1L << 25);
+    carry8 = h8 >> 26;
+    h9 += carry8;
+    h8 -= carry8 * ((uint32_t) 1L << 26);
+    carry9 = h9 >> 25;
+    h9 -= carry9 * ((uint32_t) 1L << 25);
+
+    h[0] = h0;
+    h[1] = h1;
+    h[2] = h2;
+    h[3] = h3;
+    h[4] = h4;
+    h[5] = h5;
+    h[6] = h6;
+    h[7] = h7;
+    h[8] = h8;
+    h[9] = h9;
+}
+
+/*
+ Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ Have h0+...+2^230 h9 between 0 and 2^255-1;
+ evidently 2^255 h10-2^255 q = 0.
+
+ Goal: Output h0+...+2^230 h9.
+ */
+
+void
+fe25519_tobytes(unsigned char *s, const fe25519 h)
+{
+    fe25519 t;
+
+    fe25519_reduce(t, h);
+    s[0]  = t[0] >> 0;
+    s[1]  = t[0] >> 8;
+    s[2]  = t[0] >> 16;
+    s[3]  = (t[0] >> 24) | (t[1] * ((uint32_t) 1 << 2));
+    s[4]  = t[1] >> 6;
+    s[5]  = t[1] >> 14;
+    s[6]  = (t[1] >> 22) | (t[2] * ((uint32_t) 1 << 3));
+    s[7]  = t[2] >> 5;
+    s[8]  = t[2] >> 13;
+    s[9]  = (t[2] >> 21) | (t[3] * ((uint32_t) 1 << 5));
+    s[10] = t[3] >> 3;
+    s[11] = t[3] >> 11;
+    s[12] = (t[3] >> 19) | (t[4] * ((uint32_t) 1 << 6));
+    s[13] = t[4] >> 2;
+    s[14] = t[4] >> 10;
+    s[15] = t[4] >> 18;
+    s[16] = t[5] >> 0;
+    s[17] = t[5] >> 8;
+    s[18] = t[5] >> 16;
+    s[19] = (t[5] >> 24) | (t[6] * ((uint32_t) 1 << 1));
+    s[20] = t[6] >> 7;
+    s[21] = t[6] >> 15;
+    s[22] = (t[6] >> 23) | (t[7] * ((uint32_t) 1 << 3));
+    s[23] = t[7] >> 5;
+    s[24] = t[7] >> 13;
+    s[25] = (t[7] >> 21) | (t[8] * ((uint32_t) 1 << 4));
+    s[26] = t[8] >> 4;
+    s[27] = t[8] >> 12;
+    s[28] = (t[8] >> 20) | (t[9] * ((uint32_t) 1 << 6));
+    s[29] = t[9] >> 2;
+    s[30] = t[9] >> 10;
+    s[31] = t[9] >> 18;
+}

+ 1344 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_51/base.h

@@ -0,0 +1,1344 @@
+{ /* 0/31 */
+  {
+    { 1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563 },
+    { 62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585 },
+    { 301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142 }
+  },
+  {
+    { 1380971894829527, 790832306631236, 2067202295274102, 1995808275510000, 1566530869037010 },
+    { 463307831301544, 432984605774163, 1610641361907204, 750899048855000, 1894842303421586 },
+    { 748439484463711, 1033211726465151, 1396005112841647, 1611506220286469, 1972177495910992 }
+  },
+  {
+    { 1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911 },
+    { 316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597 },
+    { 1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707 }
+  },
+  {
+    { 934282339813791, 1846903124198670, 1172395437954843, 1007037127761661, 1830588347719256 },
+    { 1694390458783935, 1735906047636159, 705069562067493, 648033061693059, 696214010414170 },
+    { 1121406372216585, 192876649532226, 190294192191717, 1994165897297032, 2245000007398739 }
+  },
+  {
+    { 769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016 },
+    { 425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893 },
+    { 1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339 }
+  },
+  {
+    { 1388594989461809, 316767091099457, 394298842192982, 1230079486801005, 1440737038838979 },
+    { 7380825640100, 146210432690483, 304903576448906, 1198869323871120, 997689833219095 },
+    { 1181317918772081, 114573476638901, 262805072233344, 265712217171332, 294181933805782 }
+  },
+  {
+    { 665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985 },
+    { 2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113 },
+    { 965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601 }
+  },
+  {
+    { 2068619540119183, 1966274918058806, 957728544705549, 729906502578991, 159834893065166 },
+    { 2073601412052185, 31021124762708, 264500969797082, 248034690651703, 1030252227928288 },
+    { 551790716293402, 1989538725166328, 801169423371717, 2052451893578887, 678432056995012 }
+  }
+},
+{ /* 1/31 */
+  {
+    { 1368953770187805, 790347636712921, 437508475667162, 2142576377050580, 1932081720066286 },
+    { 953638594433374, 1092333936795051, 1419774766716690, 805677984380077, 859228993502513 },
+    { 1200766035879111, 20142053207432, 1465634435977050, 1645256912097844, 295121984874596 }
+  },
+  {
+    { 1735718747031557, 1248237894295956, 1204753118328107, 976066523550493, 65943769534592 },
+    { 1060098822528990, 1586825862073490, 212301317240126, 1975302711403555, 666724059764335 },
+    { 1091990273418756, 1572899409348578, 80968014455247, 306009358661350, 1520450739132526 }
+  },
+  {
+    { 1480517209436112, 1511153322193952, 1244343858991172, 304788150493241, 369136856496443 },
+    { 2151330273626164, 762045184746182, 1688074332551515, 823046109005759, 907602769079491 },
+    { 2047386910586836, 168470092900250, 1552838872594810, 340951180073789, 360819374702533 }
+  },
+  {
+    { 1982622644432056, 2014393600336956, 128909208804214, 1617792623929191, 105294281913815 },
+    { 980234343912898, 1712256739246056, 588935272190264, 204298813091998, 841798321043288 },
+    { 197561292938973, 454817274782871, 1963754960082318, 2113372252160468, 971377527342673 }
+  },
+  {
+    { 164699448829328, 3127451757672, 1199504971548753, 1766155447043652, 1899238924683527 },
+    { 732262946680281, 1674412764227063, 2182456405662809, 1350894754474250, 558458873295247 },
+    { 2103305098582922, 1960809151316468, 715134605001343, 1454892949167181, 40827143824949 }
+  },
+  {
+    { 1239289043050212, 1744654158124578, 758702410031698, 1796762995074688, 1603056663766 },
+    { 2232056027107988, 987343914584615, 2115594492994461, 1819598072792159, 1119305654014850 },
+    { 320153677847348, 939613871605645, 641883205761567, 1930009789398224, 329165806634126 }
+  },
+  {
+    { 980930490474130, 1242488692177893, 1251446316964684, 1086618677993530, 1961430968465772 },
+    { 276821765317453, 1536835591188030, 1305212741412361, 61473904210175, 2051377036983058 },
+    { 833449923882501, 1750270368490475, 1123347002068295, 185477424765687, 278090826653186 }
+  },
+  {
+    { 794524995833413, 1849907304548286, 53348672473145, 1272368559505217, 1147304168324779 },
+    { 1504846112759364, 1203096289004681, 562139421471418, 274333017451844, 1284344053775441 },
+    { 483048732424432, 2116063063343382, 30120189902313, 292451576741007, 1156379271702225 }
+  }
+},
+{ /* 2/31 */
+  {
+    { 928372153029038, 2147692869914564, 1455665844462196, 1986737809425946, 185207050258089 },
+    { 137732961814206, 706670923917341, 1387038086865771, 1965643813686352, 1384777115696347 },
+    { 481144981981577, 2053319313589856, 2065402289827512, 617954271490316, 1106602634668125 }
+  },
+  {
+    { 696298019648792, 893299659040895, 1148636718636009, 26734077349617, 2203955659340681 },
+    { 657390353372855, 998499966885562, 991893336905797, 810470207106761, 343139804608786 },
+    { 791736669492960, 934767652997115, 824656780392914, 1759463253018643, 361530362383518 }
+  },
+  {
+    { 2022541353055597, 2094700262587466, 1551008075025686, 242785517418164, 695985404963562 },
+    { 1287487199965223, 2215311941380308, 1552928390931986, 1664859529680196, 1125004975265243 },
+    { 677434665154918, 989582503122485, 1817429540898386, 1052904935475344, 1143826298169798 }
+  },
+  {
+    { 367266328308408, 318431188922404, 695629353755355, 634085657580832, 24581612564426 },
+    { 773360688841258, 1815381330538070, 363773437667376, 539629987070205, 783280434248437 },
+    { 180820816194166, 168937968377394, 748416242794470, 1227281252254508, 1567587861004268 }
+  },
+  {
+    { 478775558583645, 2062896624554807, 699391259285399, 358099408427873, 1277310261461761 },
+    { 1984740906540026, 1079164179400229, 1056021349262661, 1659958556483663, 1088529069025527 },
+    { 580736401511151, 1842931091388998, 1177201471228238, 2075460256527244, 1301133425678027 }
+  },
+  {
+    { 1515728832059182, 1575261009617579, 1510246567196186, 191078022609704, 116661716289141 },
+    { 1295295738269652, 1714742313707026, 545583042462581, 2034411676262552, 1513248090013606 },
+    { 230710545179830, 30821514358353, 760704303452229, 390668103790604, 573437871383156 }
+  },
+  {
+    { 1169380107545646, 263167233745614, 2022901299054448, 819900753251120, 2023898464874585 },
+    { 2102254323485823, 1570832666216754, 34696906544624, 1993213739807337, 70638552271463 },
+    { 894132856735058, 548675863558441, 845349339503395, 1942269668326667, 1615682209874691 }
+  },
+  {
+    { 1287670217537834, 1222355136884920, 1846481788678694, 1150426571265110, 1613523400722047 },
+    { 793388516527298, 1315457083650035, 1972286999342417, 1901825953052455, 338269477222410 },
+    { 550201530671806, 778605267108140, 2063911101902983, 115500557286349, 2041641272971022 }
+  }
+},
+{ /* 3/31 */
+  {
+    { 717255318455100, 519313764361315, 2080406977303708, 541981206705521, 774328150311600 },
+    { 261715221532238, 1795354330069993, 1496878026850283, 499739720521052, 389031152673770 },
+    { 1997217696294013, 1717306351628065, 1684313917746180, 1644426076011410, 1857378133465451 }
+  },
+  {
+    { 1475434724792648, 76931896285979, 1116729029771667, 2002544139318042, 725547833803938 },
+    { 2022306639183567, 726296063571875, 315345054448644, 1058733329149221, 1448201136060677 },
+    { 1710065158525665, 1895094923036397, 123988286168546, 1145519900776355, 1607510767693874 }
+  },
+  {
+    { 561605375422540, 1071733543815037, 131496498800990, 1946868434569999, 828138133964203 },
+    { 1548495173745801, 442310529226540, 998072547000384, 553054358385281, 644824326376171 },
+    { 1445526537029440, 2225519789662536, 914628859347385, 1064754194555068, 1660295614401091 }
+  },
+  {
+    { 1199690223111956, 24028135822341, 66638289244341, 57626156285975, 565093967979607 },
+    { 876926774220824, 554618976488214, 1012056309841565, 839961821554611, 1414499340307677 },
+    { 703047626104145, 1266841406201770, 165556500219173, 486991595001879, 1011325891650656 }
+  },
+  {
+    { 1622861044480487, 1156394801573634, 1869132565415504, 327103985777730, 2095342781472284 },
+    { 334886927423922, 489511099221528, 129160865966726, 1720809113143481, 619700195649254 },
+    { 1646545795166119, 1758370782583567, 714746174550637, 1472693650165135, 898994790308209 }
+  },
+  {
+    { 333403773039279, 295772542452938, 1693106465353610, 912330357530760, 471235657950362 },
+    { 1811196219982022, 1068969825533602, 289602974833439, 1988956043611592, 863562343398367 },
+    { 906282429780072, 2108672665779781, 432396390473936, 150625823801893, 1708930497638539 }
+  },
+  {
+    { 925664675702328, 21416848568684, 1831436641861340, 601157008940113, 371818055044496 },
+    { 1479786007267725, 1738881859066675, 68646196476567, 2146507056100328, 1247662817535471 },
+    { 52035296774456, 939969390708103, 312023458773250, 59873523517659, 1231345905848899 }
+  },
+  {
+    { 643355106415761, 290186807495774, 2013561737429023, 319648069511546, 393736678496162 },
+    { 129358342392716, 1932811617704777, 1176749390799681, 398040349861790, 1170779668090425 },
+    { 2051980782668029, 121859921510665, 2048329875753063, 1235229850149665, 519062146124755 }
+  }
+},
+{ /* 4/31 */
+  {
+    { 1608170971973096, 415809060360428, 1350468408164766, 2038620059057678, 1026904485989112 },
+    { 1837656083115103, 1510134048812070, 906263674192061, 1821064197805734, 565375124676301 },
+    { 578027192365650, 2034800251375322, 2128954087207123, 478816193810521, 2196171989962750 }
+  },
+  {
+    { 1633188840273139, 852787172373708, 1548762607215796, 1266275218902681, 1107218203325133 },
+    { 462189358480054, 1784816734159228, 1611334301651368, 1303938263943540, 707589560319424 },
+    { 1038829280972848, 38176604650029, 753193246598573, 1136076426528122, 595709990562434 }
+  },
+  {
+    { 1408451820859834, 2194984964010833, 2198361797561729, 1061962440055713, 1645147963442934 },
+    { 4701053362120, 1647641066302348, 1047553002242085, 1923635013395977, 206970314902065 },
+    { 1750479161778571, 1362553355169293, 1891721260220598, 966109370862782, 1024913988299801 }
+  },
+  {
+    { 212699049131723, 1117950018299775, 1873945661751056, 1403802921984058, 130896082652698 },
+    { 636808533673210, 1262201711667560, 390951380330599, 1663420692697294, 561951321757406 },
+    { 520731594438141, 1446301499955692, 273753264629267, 1565101517999256, 1019411827004672 }
+  },
+  {
+    { 926527492029409, 1191853477411379, 734233225181171, 184038887541270, 1790426146325343 },
+    { 1464651961852572, 1483737295721717, 1519450561335517, 1161429831763785, 405914998179977 },
+    { 996126634382301, 796204125879525, 127517800546509, 344155944689303, 615279846169038 }
+  },
+  {
+    { 738724080975276, 2188666632415296, 1961313708559162, 1506545807547587, 1151301638969740 },
+    { 622917337413835, 1218989177089035, 1284857712846592, 970502061709359, 351025208117090 },
+    { 2067814584765580, 1677855129927492, 2086109782475197, 235286517313238, 1416314046739645 }
+  },
+  {
+    { 586844262630358, 307444381952195, 458399356043426, 602068024507062, 1028548203415243 },
+    { 678489922928203, 2016657584724032, 90977383049628, 1026831907234582, 615271492942522 },
+    { 301225714012278, 1094837270268560, 1202288391010439, 644352775178361, 1647055902137983 }
+  },
+  {
+    { 1210746697896478, 1416608304244708, 686487477217856, 1245131191434135, 1051238336855737 },
+    { 1135604073198207, 1683322080485474, 769147804376683, 2086688130589414, 900445683120379 },
+    { 1971518477615628, 401909519527336, 448627091057375, 1409486868273821, 1214789035034363 }
+  }
+},
+{ /* 5/31 */
+  {
+    { 1364039144731711, 1897497433586190, 2203097701135459, 145461396811251, 1349844460790699 },
+    { 1045230323257973, 818206601145807, 630513189076103, 1672046528998132, 807204017562437 },
+    { 439961968385997, 386362664488986, 1382706320807688, 309894000125359, 2207801346498567 }
+  },
+  {
+    { 1229004686397588, 920643968530863, 123975893911178, 681423993215777, 1400559197080973 },
+    { 2003766096898049, 170074059235165, 1141124258967971, 1485419893480973, 1573762821028725 },
+    { 729905708611432, 1270323270673202, 123353058984288, 426460209632942, 2195574535456672 }
+  },
+  {
+    { 1271140255321235, 2044363183174497, 52125387634689, 1445120246694705, 942541986339084 },
+    { 1761608437466135, 583360847526804, 1586706389685493, 2157056599579261, 1170692369685772 },
+    { 871476219910823, 1878769545097794, 2241832391238412, 548957640601001, 690047440233174 }
+  },
+  {
+    { 297194732135507, 1366347803776820, 1301185512245601, 561849853336294, 1533554921345731 },
+    { 999628998628371, 1132836708493400, 2084741674517453, 469343353015612, 678782988708035 },
+    { 2189427607417022, 699801937082607, 412764402319267, 1478091893643349, 2244675696854460 }
+  },
+  {
+    { 1712292055966563, 204413590624874, 1405738637332841, 408981300829763, 861082219276721 },
+    { 508561155940631, 966928475686665, 2236717801150132, 424543858577297, 2089272956986143 },
+    { 221245220129925, 1156020201681217, 491145634799213, 542422431960839, 828100817819207 }
+  },
+  {
+    { 153756971240384, 1299874139923977, 393099165260502, 1058234455773022, 996989038681183 },
+    { 559086812798481, 573177704212711, 1629737083816402, 1399819713462595, 1646954378266038 },
+    { 1887963056288059, 228507035730124, 1468368348640282, 930557653420194, 613513962454686 }
+  },
+  {
+    { 1224529808187553, 1577022856702685, 2206946542980843, 625883007765001, 279930793512158 },
+    { 1076287717051609, 1114455570543035, 187297059715481, 250446884292121, 1885187512550540 },
+    { 902497362940219, 76749815795675, 1657927525633846, 1420238379745202, 1340321636548352 }
+  },
+  {
+    { 1129576631190784, 1281994010027327, 996844254743018, 257876363489249, 1150850742055018 },
+    { 628740660038789, 1943038498527841, 467786347793886, 1093341428303375, 235413859513003 },
+    { 237425418909360, 469614029179605, 1512389769174935, 1241726368345357, 441602891065214 }
+  }
+},
+{ /* 6/31 */
+  {
+    { 1736417953058555, 726531315520508, 1833335034432527, 1629442561574747, 624418919286085 },
+    { 1960754663920689, 497040957888962, 1909832851283095, 1271432136996826, 2219780368020940 },
+    { 1537037379417136, 1358865369268262, 2130838645654099, 828733687040705, 1999987652890901 }
+  },
+  {
+    { 629042105241814, 1098854999137608, 887281544569320, 1423102019874777, 7911258951561 },
+    { 1811562332665373, 1501882019007673, 2213763501088999, 359573079719636, 36370565049116 },
+    { 218907117361280, 1209298913016966, 1944312619096112, 1130690631451061, 1342327389191701 }
+  },
+  {
+    { 1369976867854704, 1396479602419169, 1765656654398856, 2203659200586299, 998327836117241 },
+    { 2230701885562825, 1348173180338974, 2172856128624598, 1426538746123771, 444193481326151 },
+    { 784210426627951, 918204562375674, 1284546780452985, 1324534636134684, 1872449409642708 }
+  },
+  {
+    { 319638829540294, 596282656808406, 2037902696412608, 1557219121643918, 341938082688094 },
+    { 1901860206695915, 2004489122065736, 1625847061568236, 973529743399879, 2075287685312905 },
+    { 1371853944110545, 1042332820512553, 1949855697918254, 1791195775521505, 37487364849293 }
+  },
+  {
+    { 687200189577855, 1082536651125675, 644224940871546, 340923196057951, 343581346747396 },
+    { 2082717129583892, 27829425539422, 145655066671970, 1690527209845512, 1865260509673478 },
+    { 1059729620568824, 2163709103470266, 1440302280256872, 1769143160546397, 869830310425069 }
+  },
+  {
+    { 1609516219779025, 777277757338817, 2101121130363987, 550762194946473, 1905542338659364 },
+    { 2024821921041576, 426948675450149, 595133284085473, 471860860885970, 600321679413000 },
+    { 598474602406721, 1468128276358244, 1191923149557635, 1501376424093216, 1281662691293476 }
+  },
+  {
+    { 1721138489890707, 1264336102277790, 433064545421287, 1359988423149466, 1561871293409447 },
+    { 719520245587143, 393380711632345, 132350400863381, 1543271270810729, 1819543295798660 },
+    { 396397949784152, 1811354474471839, 1362679985304303, 2117033964846756, 498041172552279 }
+  },
+  {
+    { 1812471844975748, 1856491995543149, 126579494584102, 1036244859282620, 1975108050082550 },
+    { 650623932407995, 1137551288410575, 2125223403615539, 1725658013221271, 2134892965117796 },
+    { 522584000310195, 1241762481390450, 1743702789495384, 2227404127826575, 1686746002148897 }
+  }
+},
+{ /* 7/31 */
+  {
+    { 427904865186312, 1703211129693455, 1585368107547509, 1436984488744336, 761188534613978 },
+    { 318101947455002, 248138407995851, 1481904195303927, 309278454311197, 1258516760217879 },
+    { 1275068538599310, 513726919533379, 349926553492294, 688428871968420, 1702400196000666 }
+  },
+  {
+    { 1061864036265233, 961611260325381, 321859632700838, 1045600629959517, 1985130202504038 },
+    { 1558816436882417, 1962896332636523, 1337709822062152, 1501413830776938, 294436165831932 },
+    { 818359826554971, 1862173000996177, 626821592884859, 573655738872376, 1749691246745455 }
+  },
+  {
+    { 1988022651432119, 1082111498586040, 1834020786104821, 1454826876423687, 692929915223122 },
+    { 2146513703733331, 584788900394667, 464965657279958, 2183973639356127, 238371159456790 },
+    { 1129007025494441, 2197883144413266, 265142755578169, 971864464758890, 1983715884903702 }
+  },
+  {
+    { 1291366624493075, 381456718189114, 1711482489312444, 1815233647702022, 892279782992467 },
+    { 444548969917454, 1452286453853356, 2113731441506810, 645188273895859, 810317625309512 },
+    { 2242724082797924, 1373354730327868, 1006520110883049, 2147330369940688, 1151816104883620 }
+  },
+  {
+    { 1745720200383796, 1911723143175317, 2056329390702074, 355227174309849, 879232794371100 },
+    { 163723479936298, 115424889803150, 1156016391581227, 1894942220753364, 1970549419986329 },
+    { 681981452362484, 267208874112496, 1374683991933094, 638600984916117, 646178654558546 }
+  },
+  {
+    { 13378654854251, 106237307029567, 1944412051589651, 1841976767925457, 230702819835573 },
+    { 260683893467075, 854060306077237, 913639551980112, 4704576840123, 280254810808712 },
+    { 715374893080287, 1173334812210491, 1806524662079626, 1894596008000979, 398905715033393 }
+  },
+  {
+    { 500026409727661, 1596431288195371, 1420380351989370, 985211561521489, 392444930785633 },
+    { 2096421546958141, 1922523000950363, 789831022876840, 427295144688779, 320923973161730 },
+    { 1927770723575450, 1485792977512719, 1850996108474547, 551696031508956, 2126047405475647 }
+  },
+  {
+    { 2112099158080148, 742570803909715, 6484558077432, 1951119898618916, 93090382703416 },
+    { 383905201636970, 859946997631870, 855623867637644, 1017125780577795, 794250831877809 },
+    { 77571826285752, 999304298101753, 487841111777762, 1038031143212339, 339066367948762 }
+  }
+},
+{ /* 8/31 */
+  {
+    { 674994775520533, 266035846330789, 826951213393478, 1405007746162285, 1781791018620876 },
+    { 1001412661522686, 348196197067298, 1666614366723946, 888424995032760, 580747687801357 },
+    { 1939560076207777, 1409892634407635, 552574736069277, 383854338280405, 190706709864139 }
+  },
+  {
+    { 2177087163428741, 1439255351721944, 1208070840382793, 2230616362004769, 1396886392021913 },
+    { 676962063230039, 1880275537148808, 2046721011602706, 888463247083003, 1318301552024067 },
+    { 1466980508178206, 617045217998949, 652303580573628, 757303753529064, 207583137376902 }
+  },
+  {
+    { 1511056752906902, 105403126891277, 493434892772846, 1091943425335976, 1802717338077427 },
+    { 1853982405405128, 1878664056251147, 1528011020803992, 1019626468153565, 1128438412189035 },
+    { 1963939888391106, 293456433791664, 697897559513649, 985882796904380, 796244541237972 }
+  },
+  {
+    { 416770998629779, 389655552427054, 1314476859406756, 1749382513022778, 1161905598739491 },
+    { 1428358296490651, 1027115282420478, 304840698058337, 441410174026628, 1819358356278573 },
+    { 204943430200135, 1554861433819175, 216426658514651, 264149070665950, 2047097371738319 }
+  },
+  {
+    { 1934415182909034, 1393285083565062, 516409331772960, 1157690734993892, 121039666594268 },
+    { 662035583584445, 286736105093098, 1131773000510616, 818494214211439, 472943792054479 },
+    { 665784778135882, 1893179629898606, 808313193813106, 276797254706413, 1563426179676396 }
+  },
+  {
+    { 945205108984232, 526277562959295, 1324180513733566, 1666970227868664, 153547609289173 },
+    { 2031433403516252, 203996615228162, 170487168837083, 981513604791390, 843573964916831 },
+    { 1476570093962618, 838514669399805, 1857930577281364, 2017007352225784, 317085545220047 }
+  },
+  {
+    { 1461557121912842, 1600674043318359, 2157134900399597, 1670641601940616, 127765583803283 },
+    { 1293543509393474, 2143624609202546, 1058361566797508, 214097127393994, 946888515472729 },
+    { 357067959932916, 1290876214345711, 521245575443703, 1494975468601005, 800942377643885 }
+  },
+  {
+    { 566116659100033, 820247422481740, 994464017954148, 327157611686365, 92591318111744 },
+    { 617256647603209, 1652107761099439, 1857213046645471, 1085597175214970, 817432759830522 },
+    { 771808161440705, 1323510426395069, 680497615846440, 851580615547985, 1320806384849017 }
+  }
+},
+{ /* 9/31 */
+  {
+    { 1219260086131915, 647169006596815, 79601124759706, 2161724213426748, 404861897060198 },
+    { 1327968293887866, 1335500852943256, 1401587164534264, 558137311952440, 1551360549268902 },
+    { 417621685193956, 1429953819744454, 396157358457099, 1940470778873255, 214000046234152 }
+  },
+  {
+    { 1268047918491973, 2172375426948536, 1533916099229249, 1761293575457130, 1590622667026765 },
+    { 1627072914981959, 2211603081280073, 1912369601616504, 1191770436221309, 2187309757525860 },
+    { 1149147819689533, 378692712667677, 828475842424202, 2218619146419342, 70688125792186 }
+  },
+  {
+    { 1299739417079761, 1438616663452759, 1536729078504412, 2053896748919838, 1008421032591246 },
+    { 2040723824657366, 399555637875075, 632543375452995, 872649937008051, 1235394727030233 },
+    { 2211311599327900, 2139787259888175, 938706616835350, 12609661139114, 2081897930719789 }
+  },
+  {
+    { 1324994503390450, 336982330582631, 1183998925654177, 1091654665913274, 48727673971319 },
+    { 1845522914617879, 1222198248335542, 150841072760134, 1927029069940982, 1189913404498011 },
+    { 1079559557592645, 2215338383666441, 1903569501302605, 49033973033940, 305703433934152 }
+  },
+  {
+    { 94653405416909, 1386121349852999, 1062130477891762, 36553947479274, 833669648948846 },
+    { 1432015813136298, 440364795295369, 1395647062821501, 1976874522764578, 934452372723352 },
+    { 1296625309219774, 2068273464883862, 1858621048097805, 1492281814208508, 2235868981918946 }
+  },
+  {
+    { 1490330266465570, 1858795661361448, 1436241134969763, 294573218899647, 1208140011028933 },
+    { 1282462923712748, 741885683986255, 2027754642827561, 518989529541027, 1826610009555945 },
+    { 1525827120027511, 723686461809551, 1597702369236987, 244802101764964, 1502833890372311 }
+  },
+  {
+    { 113622036244513, 1233740067745854, 674109952278496, 2114345180342965, 166764512856263 },
+    { 2041668749310338, 2184405322203901, 1633400637611036, 2110682505536899, 2048144390084644 },
+    { 503058759232932, 760293024620937, 2027152777219493, 666858468148475, 1539184379870952 }
+  },
+  {
+    { 1916168475367211, 915626432541343, 883217071712575, 363427871374304, 1976029821251593 },
+    { 678039535434506, 570587290189340, 1605302676614120, 2147762562875701, 1706063797091704 },
+    { 1439489648586438, 2194580753290951, 832380563557396, 561521973970522, 584497280718389 }
+  }
+},
+{ /* 10/31 */
+  {
+    { 187989455492609, 681223515948275, 1933493571072456, 1872921007304880, 488162364135671 },
+    { 1413466089534451, 410844090765630, 1397263346404072, 408227143123410, 1594561803147811 },
+    { 2102170800973153, 719462588665004, 1479649438510153, 1097529543970028, 1302363283777685 }
+  },
+  {
+    { 942065717847195, 1069313679352961, 2007341951411051, 70973416446291, 1419433790163706 },
+    { 1146565545556377, 1661971299445212, 406681704748893, 564452436406089, 1109109865829139 },
+    { 2214421081775077, 1165671861210569, 1890453018796184, 3556249878661, 442116172656317 }
+  },
+  {
+    { 753830546620811, 1666955059895019, 1530775289309243, 1119987029104146, 2164156153857580 },
+    { 615171919212796, 1523849404854568, 854560460547503, 2067097370290715, 1765325848586042 },
+    { 1094538949313667, 1796592198908825, 870221004284388, 2025558921863561, 1699010892802384 }
+  },
+  {
+    { 1951351290725195, 1916457206844795, 198025184438026, 1909076887557595, 1938542290318919 },
+    { 1014323197538413, 869150639940606, 1756009942696599, 1334952557375672, 1544945379082874 },
+    { 764055910920305, 1603590757375439, 146805246592357, 1843313433854297, 954279890114939 }
+  },
+  {
+    { 80113526615750, 764536758732259, 1055139345100233, 469252651759390, 617897512431515 },
+    { 74497112547268, 740094153192149, 1745254631717581, 727713886503130, 1283034364416928 },
+    { 525892105991110, 1723776830270342, 1476444848991936, 573789489857760, 133864092632978 }
+  },
+  {
+    { 542611720192581, 1986812262899321, 1162535242465837, 481498966143464, 544600533583622 },
+    { 64123227344372, 1239927720647794, 1360722983445904, 222610813654661, 62429487187991 },
+    { 1793193323953132, 91096687857833, 70945970938921, 2158587638946380, 1537042406482111 }
+  },
+  {
+    { 1895854577604609, 1394895708949416, 1728548428495944, 1140864900240149, 563645333603061 },
+    { 141358280486863, 91435889572504, 1087208572552643, 1829599652522921, 1193307020643647 },
+    { 1611230858525381, 950720175540785, 499589887488610, 2001656988495019, 88977313255908 }
+  },
+  {
+    { 1189080501479658, 2184348804772597, 1040818725742319, 2018318290311834, 1712060030915354 },
+    { 873966876953756, 1090638350350440, 1708559325189137, 672344594801910, 1320437969700239 },
+    { 1508590048271766, 1131769479776094, 101550868699323, 428297785557897, 561791648661744 }
+  }
+},
+{ /* 11/31 */
+  {
+    { 756417570499462, 237882279232602, 2136263418594016, 1701968045454886, 703713185137472 },
+    { 1781187809325462, 1697624151492346, 1381393690939988, 175194132284669, 1483054666415238 },
+    { 2175517777364616, 708781536456029, 955668231122942, 1967557500069555, 2021208005604118 }
+  },
+  {
+    { 1115135966606887, 224217372950782, 915967306279222, 593866251291540, 561747094208006 },
+    { 1443163092879439, 391875531646162, 2180847134654632, 464538543018753, 1594098196837178 },
+    { 850858855888869, 319436476624586, 327807784938441, 740785849558761, 17128415486016 }
+  },
+  {
+    { 2132756334090067, 536247820155645, 48907151276867, 608473197600695, 1261689545022784 },
+    { 1525176236978354, 974205476721062, 293436255662638, 148269621098039, 137961998433963 },
+    { 1121075518299410, 2071745529082111, 1265567917414828, 1648196578317805, 496232102750820 }
+  },
+  {
+    { 122321229299801, 1022922077493685, 2001275453369484, 2017441881607947, 993205880778002 },
+    { 654925550560074, 1168810995576858, 575655959430926, 905758704861388, 496774564663534 },
+    { 1954109525779738, 2117022646152485, 338102630417180, 1194140505732026, 107881734943492 }
+  },
+  {
+    { 1714785840001267, 2036500018681589, 1876380234251966, 2056717182974196, 1645855254384642 },
+    { 106431476499341, 62482972120563, 1513446655109411, 807258751769522, 538491469114 },
+    { 2002850762893643, 1243624520538135, 1486040410574605, 2184752338181213, 378495998083531 }
+  },
+  {
+    { 922510868424903, 1089502620807680, 402544072617374, 1131446598479839, 1290278588136533 },
+    { 1867998812076769, 715425053580701, 39968586461416, 2173068014586163, 653822651801304 },
+    { 162892278589453, 182585796682149, 75093073137630, 497037941226502, 133871727117371 }
+  },
+  {
+    { 1914596576579670, 1608999621851578, 1987629837704609, 1519655314857977, 1819193753409464 },
+    { 1949315551096831, 1069003344994464, 1939165033499916, 1548227205730856, 1933767655861407 },
+    { 1730519386931635, 1393284965610134, 1597143735726030, 416032382447158, 1429665248828629 }
+  },
+  {
+    { 360275475604565, 547835731063078, 215360904187529, 596646739879007, 332709650425085 },
+    { 47602113726801, 1522314509708010, 437706261372925, 814035330438027, 335930650933545 },
+    { 1291597595523886, 1058020588994081, 402837842324045, 1363323695882781, 2105763393033193 }
+  }
+},
+{ /* 12/31 */
+  {
+    { 109521982566564, 1715257748585139, 1112231216891516, 2046641005101484, 134249157157013 },
+    { 2156991030936798, 2227544497153325, 1869050094431622, 754875860479115, 1754242344267058 },
+    { 1846089562873800, 98894784984326, 1412430299204844, 171351226625762, 1100604760929008 }
+  },
+  {
+    { 84172382130492, 499710970700046, 425749630620778, 1762872794206857, 612842602127960 },
+    { 868309334532756, 1703010512741873, 1952690008738057, 4325269926064, 2071083554962116 },
+    { 523094549451158, 401938899487815, 1407690589076010, 2022387426254453, 158660516411257 }
+  },
+  {
+    { 612867287630009, 448212612103814, 571629077419196, 1466796750919376, 1728478129663858 },
+    { 1723848973783452, 2208822520534681, 1718748322776940, 1974268454121942, 1194212502258141 },
+    { 1254114807944608, 977770684047110, 2010756238954993, 1783628927194099, 1525962994408256 }
+  },
+  {
+    { 232464058235826, 1948628555342434, 1835348780427694, 1031609499437291, 64472106918373 },
+    { 767338676040683, 754089548318405, 1523192045639075, 435746025122062, 512692508440385 },
+    { 1255955808701983, 1700487367990941, 1166401238800299, 1175121994891534, 1190934801395380 }
+  },
+  {
+    { 349144008168292, 1337012557669162, 1475912332999108, 1321618454900458, 47611291904320 },
+    { 877519947135419, 2172838026132651, 272304391224129, 1655143327559984, 886229406429814 },
+    { 375806028254706, 214463229793940, 572906353144089, 572168269875638, 697556386112979 }
+  },
+  {
+    { 1168827102357844, 823864273033637, 2071538752104697, 788062026895924, 599578340743362 },
+    { 1948116082078088, 2054898304487796, 2204939184983900, 210526805152138, 786593586607626 },
+    { 1915320147894736, 156481169009469, 655050471180417, 592917090415421, 2165897438660879 }
+  },
+  {
+    { 1726336468579724, 1119932070398949, 1929199510967666, 33918788322959, 1836837863503150 },
+    { 829996854845988, 217061778005138, 1686565909803640, 1346948817219846, 1723823550730181 },
+    { 384301494966394, 687038900403062, 2211195391021739, 254684538421383, 1245698430589680 }
+  },
+  {
+    { 1247567493562688, 1978182094455847, 183871474792955, 806570235643435, 288461518067916 },
+    { 1449077384734201, 38285445457996, 2136537659177832, 2146493000841573, 725161151123125 },
+    { 1201928866368855, 800415690605445, 1703146756828343, 997278587541744, 1858284414104014 }
+  }
+},
+{ /* 13/31 */
+  {
+    { 356468809648877, 782373916933152, 1718002439402870, 1392222252219254, 663171266061951 },
+    { 759628738230460, 1012693474275852, 353780233086498, 246080061387552, 2030378857679162 },
+    { 2040672435071076, 888593182036908, 1298443657189359, 1804780278521327, 354070726137060 }
+  },
+  {
+    { 1894938527423184, 1463213041477277, 474410505497651, 247294963033299, 877975941029128 },
+    { 207937160991127, 12966911039119, 820997788283092, 1010440472205286, 1701372890140810 },
+    { 218882774543183, 533427444716285, 1233243976733245, 435054256891319, 1509568989549904 }
+  },
+  {
+    { 1888838535711826, 1052177758340622, 1213553803324135, 169182009127332, 463374268115872 },
+    { 299137589460312, 1594371588983567, 868058494039073, 257771590636681, 1805012993142921 },
+    { 1806842755664364, 2098896946025095, 1356630998422878, 1458279806348064, 347755825962072 }
+  },
+  {
+    { 1402334161391744, 1560083671046299, 1008585416617747, 1147797150908892, 1420416683642459 },
+    { 665506704253369, 273770475169863, 799236974202630, 848328990077558, 1811448782807931 },
+    { 1468412523962641, 771866649897997, 1931766110147832, 799561180078482, 524837559150077 }
+  },
+  {
+    { 2223212657821850, 630416247363666, 2144451165500328, 816911130947791, 1024351058410032 },
+    { 1266603897524861, 156378408858100, 1275649024228779, 447738405888420, 253186462063095 },
+    { 2022215964509735, 136144366993649, 1800716593296582, 1193970603800203, 871675847064218 }
+  },
+  {
+    { 1862751661970328, 851596246739884, 1519315554814041, 1542798466547449, 1417975335901520 },
+    { 1228168094547481, 334133883362894, 587567568420081, 433612590281181, 603390400373205 },
+    { 121893973206505, 1843345804916664, 1703118377384911, 497810164760654, 101150811654673 }
+  },
+  {
+    { 458346255946468, 290909935619344, 1452768413850679, 550922875254215, 1537286854336538 },
+    { 584322311184395, 380661238802118, 114839394528060, 655082270500073, 2111856026034852 },
+    { 996965581008991, 2148998626477022, 1012273164934654, 1073876063914522, 1688031788934939 }
+  },
+  {
+    { 923487018849600, 2085106799623355, 528082801620136, 1606206360876188, 735907091712524 },
+    { 1697697887804317, 1335343703828273, 831288615207040, 949416685250051, 288760277392022 },
+    { 1419122478109648, 1325574567803701, 602393874111094, 2107893372601700, 1314159682671307 }
+  }
+},
+{ /* 14/31 */
+  {
+    { 2201150872731804, 2180241023425241, 97663456423163, 1633405770247824, 848945042443986 },
+    { 1173339555550611, 818605084277583, 47521504364289, 924108720564965, 735423405754506 },
+    { 830104860549448, 1886653193241086, 1600929509383773, 1475051275443631, 286679780900937 }
+  },
+  {
+    { 1577111294832995, 1030899169768747, 144900916293530, 1964672592979567, 568390100955250 },
+    { 278388655910247, 487143369099838, 927762205508727, 181017540174210, 1616886700741287 },
+    { 1191033906638969, 940823957346562, 1606870843663445, 861684761499847, 658674867251089 }
+  },
+  {
+    { 1875032594195546, 1427106132796197, 724736390962158, 901860512044740, 635268497268760 },
+    { 622869792298357, 1903919278950367, 1922588621661629, 1520574711600434, 1087100760174640 },
+    { 25465949416618, 1693639527318811, 1526153382657203, 125943137857169, 145276964043999 }
+  },
+  {
+    { 214739857969358, 920212862967915, 1939901550972269, 1211862791775221, 85097515720120 },
+    { 2006245852772938, 734762734836159, 254642929763427, 1406213292755966, 239303749517686 },
+    { 1619678837192149, 1919424032779215, 1357391272956794, 1525634040073113, 1310226789796241 }
+  },
+  {
+    { 1040763709762123, 1704449869235352, 605263070456329, 1998838089036355, 1312142911487502 },
+    { 1996723311435669, 1844342766567060, 985455700466044, 1165924681400960, 311508689870129 },
+    { 43173156290518, 2202883069785309, 1137787467085917, 1733636061944606, 1394992037553852 }
+  },
+  {
+    { 670078326344559, 555655025059356, 471959386282438, 2141455487356409, 849015953823125 },
+    { 2197214573372804, 794254097241315, 1030190060513737, 267632515541902, 2040478049202624 },
+    { 1812516004670529, 1609256702920783, 1706897079364493, 258549904773295, 996051247540686 }
+  },
+  {
+    { 1540374301420584, 1764656898914615, 1810104162020396, 923808779163088, 664390074196579 },
+    { 1323460699404750, 1262690757880991, 871777133477900, 1060078894988977, 1712236889662886 },
+    { 1696163952057966, 1391710137550823, 608793846867416, 1034391509472039, 1780770894075012 }
+  },
+  {
+    { 1367603834210841, 2131988646583224, 890353773628144, 1908908219165595, 270836895252891 },
+    { 597536315471731, 40375058742586, 1942256403956049, 1185484645495932, 312666282024145 },
+    { 1919411405316294, 1234508526402192, 1066863051997083, 1008444703737597, 1348810787701552 }
+  }
+},
+{ /* 15/31 */
+  {
+    { 2102881477513865, 1570274565945361, 1573617900503708, 18662635732583, 2232324307922098 },
+    { 1853931367696942, 8107973870707, 350214504129299, 775206934582587, 1752317649166792 },
+    { 1417148368003523, 721357181628282, 505725498207811, 373232277872983, 261634707184480 }
+  },
+  {
+    { 2186733281493267, 2250694917008620, 1014829812957440, 479998161452389, 83566193876474 },
+    { 1268116367301224, 560157088142809, 802626839600444, 2210189936605713, 1129993785579988 },
+    { 615183387352312, 917611676109240, 878893615973325, 978940963313282, 938686890583575 }
+  },
+  {
+    { 522024729211672, 1045059315315808, 1892245413707790, 1907891107684253, 2059998109500714 },
+    { 1799679152208884, 912132775900387, 25967768040979, 432130448590461, 274568990261996 },
+    { 98698809797682, 2144627600856209, 1907959298569602, 811491302610148, 1262481774981493 }
+  },
+  {
+    { 1791451399743152, 1713538728337276, 118349997257490, 1882306388849954, 158235232210248 },
+    { 1217809823321928, 2173947284933160, 1986927836272325, 1388114931125539, 12686131160169 },
+    { 1650875518872272, 1136263858253897, 1732115601395988, 734312880662190, 1252904681142109 }
+  },
+  {
+    { 372986456113865, 525430915458171, 2116279931702135, 501422713587815, 1907002872974925 },
+    { 803147181835288, 868941437997146, 316299302989663, 943495589630550, 571224287904572 },
+    { 227742695588364, 1776969298667369, 628602552821802, 457210915378118, 2041906378111140 }
+  },
+  {
+    { 815000523470260, 913085688728307, 1052060118271173, 1345536665214223, 541623413135555 },
+    { 1580216071604333, 1877997504342444, 857147161260913, 703522726778478, 2182763974211603 },
+    { 1870080310923419, 71988220958492, 1783225432016732, 615915287105016, 1035570475990230 }
+  },
+  {
+    { 730987750830150, 857613889540280, 1083813157271766, 1002817255970169, 1719228484436074 },
+    { 377616581647602, 1581980403078513, 804044118130621, 2034382823044191, 643844048472185 },
+    { 176957326463017, 1573744060478586, 528642225008045, 1816109618372371, 1515140189765006 }
+  },
+  {
+    { 1888911448245718, 1387110895611080, 1924503794066429, 1731539523700949, 2230378382645454 },
+    { 443392177002051, 233793396845137, 2199506622312416, 1011858706515937, 974676837063129 },
+    { 1846351103143623, 1949984838808427, 671247021915253, 1946756846184401, 1929296930380217 }
+  }
+},
+{ /* 16/31 */
+  {
+    { 849646212452002, 1410198775302919, 73767886183695, 1641663456615812, 762256272452411 },
+    { 692017667358279, 723305578826727, 1638042139863265, 748219305990306, 334589200523901 },
+    { 22893968530686, 2235758574399251, 1661465835630252, 925707319443452, 1203475116966621 }
+  },
+  {
+    { 801299035785166, 1733292596726131, 1664508947088596, 467749120991922, 1647498584535623 },
+    { 903105258014366, 427141894933047, 561187017169777, 1884330244401954, 1914145708422219 },
+    { 1344191060517578, 1960935031767890, 1518838929955259, 1781502350597190, 1564784025565682 }
+  },
+  {
+    { 673723351748086, 1979969272514923, 1175287312495508, 1187589090978666, 1881897672213940 },
+    { 1917185587363432, 1098342571752737, 5935801044414, 2000527662351839, 1538640296181569 },
+    { 2495540013192, 678856913479236, 224998292422872, 219635787698590, 1972465269000940 }
+  },
+  {
+    { 271413961212179, 1353052061471651, 344711291283483, 2014925838520662, 2006221033113941 },
+    { 194583029968109, 514316781467765, 829677956235672, 1676415686873082, 810104584395840 },
+    { 1980510813313589, 1948645276483975, 152063780665900, 129968026417582, 256984195613935 }
+  },
+  {
+    { 1860190562533102, 1936576191345085, 461100292705964, 1811043097042830, 957486749306835 },
+    { 796664815624365, 1543160838872951, 1500897791837765, 1667315977988401, 599303877030711 },
+    { 1151480509533204, 2136010406720455, 738796060240027, 319298003765044, 1150614464349587 }
+  },
+  {
+    { 1731069268103150, 735642447616087, 1364750481334268, 417232839982871, 927108269127661 },
+    { 1017222050227968, 1987716148359, 2234319589635701, 621282683093392, 2132553131763026 },
+    { 1567828528453324, 1017807205202360, 565295260895298, 829541698429100, 307243822276582 }
+  },
+  {
+    { 249079270936248, 1501514259790706, 947909724204848, 944551802437487, 552658763982480 },
+    { 2089966982947227, 1854140343916181, 2151980759220007, 2139781292261749, 158070445864917 },
+    { 1338766321464554, 1906702607371284, 1519569445519894, 115384726262267, 1393058953390992 }
+  },
+  {
+    { 1364621558265400, 1512388234908357, 1926731583198686, 2041482526432505, 920401122333774 },
+    { 1884844597333588, 601480070269079, 620203503079537, 1079527400117915, 1202076693132015 },
+    { 840922919763324, 727955812569642, 1303406629750194, 522898432152867, 294161410441865 }
+  }
+},
+{ /* 17/31 */
+  {
+    { 353760790835310, 1598361541848743, 1122905698202299, 1922533590158905, 419107700666580 },
+    { 359856369838236, 180914355488683, 861726472646627, 218807937262986, 575626773232501 },
+    { 755467689082474, 909202735047934, 730078068932500, 936309075711518, 2007798262842972 }
+  },
+  {
+    { 1609384177904073, 362745185608627, 1335318541768201, 800965770436248, 547877979267412 },
+    { 984339177776787, 815727786505884, 1645154585713747, 1659074964378553, 1686601651984156 },
+    { 1697863093781930, 599794399429786, 1104556219769607, 830560774794755, 12812858601017 }
+  },
+  {
+    { 1168737550514982, 897832437380552, 463140296333799, 302564600022547, 2008360505135501 },
+    { 1856930662813910, 678090852002597, 1920179140755167, 1259527833759868, 55540971895511 },
+    { 1158643631044921, 476554103621892, 178447851439725, 1305025542653569, 103433927680625 }
+  },
+  {
+    { 2176793111709008, 1576725716350391, 2009350167273523, 2012390194631546, 2125297410909580 },
+    { 825403285195098, 2144208587560784, 1925552004644643, 1915177840006985, 1015952128947864 },
+    { 1807108316634472, 1534392066433717, 347342975407218, 1153820745616376, 7375003497471 }
+  },
+  {
+    { 983061001799725, 431211889901241, 2201903782961093, 817393911064341, 2214616493042167 },
+    { 228567918409756, 865093958780220, 358083886450556, 159617889659320, 1360637926292598 },
+    { 234147501399755, 2229469128637390, 2175289352258889, 1397401514549353, 1885288963089922 }
+  },
+  {
+    { 1111762412951562, 252849572507389, 1048714233823341, 146111095601446, 1237505378776770 },
+    { 1113790697840279, 1051167139966244, 1045930658550944, 2011366241542643, 1686166824620755 },
+    { 1054097349305049, 1872495070333352, 182121071220717, 1064378906787311, 100273572924182 }
+  },
+  {
+    { 1306410853171605, 1627717417672447, 50983221088417, 1109249951172250, 870201789081392 },
+    { 104233794644221, 1548919791188248, 2224541913267306, 2054909377116478, 1043803389015153 },
+    { 216762189468802, 707284285441622, 190678557969733, 973969342604308, 1403009538434867 }
+  },
+  {
+    { 1279024291038477, 344776835218310, 273722096017199, 1834200436811442, 634517197663804 },
+    { 343805853118335, 1302216857414201, 566872543223541, 2051138939539004, 321428858384280 },
+    { 470067171324852, 1618629234173951, 2000092177515639, 7307679772789, 1117521120249968 }
+  }
+},
+{ /* 18/31 */
+  {
+    { 278151578291475, 1810282338562947, 1771599529530998, 1383659409671631, 685373414471841 },
+    { 577009397403102, 1791440261786291, 2177643735971638, 174546149911960, 1412505077782326 },
+    { 893719721537457, 1201282458018197, 1522349501711173, 58011597740583, 1130406465887139 }
+  },
+  {
+    { 412607348255453, 1280455764199780, 2233277987330768, 14180080401665, 331584698417165 },
+    { 262483770854550, 990511055108216, 526885552771698, 571664396646158, 354086190278723 },
+    { 1820352417585487, 24495617171480, 1547899057533253, 10041836186225, 480457105094042 }
+  },
+  {
+    { 2023310314989233, 637905337525881, 2106474638900687, 557820711084072, 1687858215057826 },
+    { 1144168702609745, 604444390410187, 1544541121756138, 1925315550126027, 626401428894002 },
+    { 1922168257351784, 2018674099908659, 1776454117494445, 956539191509034, 36031129147635 }
+  },
+  {
+    { 544644538748041, 1039872944430374, 876750409130610, 710657711326551, 1216952687484972 },
+    { 58242421545916, 2035812695641843, 2118491866122923, 1191684463816273, 46921517454099 },
+    { 272268252444639, 1374166457774292, 2230115177009552, 1053149803909880, 1354288411641016 }
+  },
+  {
+    { 1857910905368338, 1754729879288912, 885945464109877, 1516096106802166, 1602902393369811 },
+    { 1193437069800958, 901107149704790, 999672920611411, 477584824802207, 364239578697845 },
+    { 886299989548838, 1538292895758047, 1590564179491896, 1944527126709657, 837344427345298 }
+  },
+  {
+    { 754558365378305, 1712186480903618, 1703656826337531, 750310918489786, 518996040250900 },
+    { 1309847803895382, 1462151862813074, 211370866671570, 1544595152703681, 1027691798954090 },
+    { 803217563745370, 1884799722343599, 1357706345069218, 2244955901722095, 730869460037413 }
+  },
+  {
+    { 689299471295966, 1831210565161071, 1375187341585438, 1106284977546171, 1893781834054269 },
+    { 696351368613042, 1494385251239250, 738037133616932, 636385507851544, 927483222611406 },
+    { 1949114198209333, 1104419699537997, 783495707664463, 1747473107602770, 2002634765788641 }
+  },
+  {
+    { 1607325776830197, 530883941415333, 1451089452727895, 1581691157083423, 496100432831154 },
+    { 1068900648804224, 2006891997072550, 1134049269345549, 1638760646180091, 2055396084625778 },
+    { 2222475519314561, 1870703901472013, 1884051508440561, 1344072275216753, 1318025677799069 }
+  }
+},
+{ /* 19/31 */
+  {
+    { 155711679280656, 681100400509288, 389811735211209, 2135723811340709, 408733211204125 },
+    { 7813206966729, 194444201427550, 2071405409526507, 1065605076176312, 1645486789731291 },
+    { 16625790644959, 1647648827778410, 1579910185572704, 436452271048548, 121070048451050 }
+  },
+  {
+    { 1037263028552531, 568385780377829, 297953104144430, 1558584511931211, 2238221839292471 },
+    { 190565267697443, 672855706028058, 338796554369226, 337687268493904, 853246848691734 },
+    { 1763863028400139, 766498079432444, 1321118624818005, 69494294452268, 858786744165651 }
+  },
+  {
+    { 1292056768563024, 1456632109855638, 1100631247050184, 1386133165675321, 1232898350193752 },
+    { 366253102478259, 525676242508811, 1449610995265438, 1183300845322183, 185960306491545 },
+    { 28315355815982, 460422265558930, 1799675876678724, 1969256312504498, 1051823843138725 }
+  },
+  {
+    { 156914999361983, 1606148405719949, 1665208410108430, 317643278692271, 1383783705665320 },
+    { 54684536365732, 2210010038536222, 1194984798155308, 535239027773705, 1516355079301361 },
+    { 1484387703771650, 198537510937949, 2186282186359116, 617687444857508, 647477376402122 }
+  },
+  {
+    { 2147715541830533, 500032538445817, 646380016884826, 352227855331122, 1488268620408052 },
+    { 159386186465542, 1877626593362941, 618737197060512, 1026674284330807, 1158121760792685 },
+    { 1744544377739822, 1964054180355661, 1685781755873170, 2169740670377448, 1286112621104591 }
+  },
+  {
+    { 81977249784993, 1667943117713086, 1668983819634866, 1605016835177615, 1353960708075544 },
+    { 1602253788689063, 439542044889886, 2220348297664483, 657877410752869, 157451572512238 },
+    { 1029287186166717, 65860128430192, 525298368814832, 1491902500801986, 1461064796385400 }
+  },
+  {
+    { 408216988729246, 2121095722306989, 913562102267595, 1879708920318308, 241061448436731 },
+    { 1185483484383269, 1356339572588553, 584932367316448, 102132779946470, 1792922621116791 },
+    { 1966196870701923, 2230044620318636, 1425982460745905, 261167817826569, 46517743394330 }
+  },
+  {
+    { 107077591595359, 884959942172345, 27306869797400, 2224911448949390, 964352058245223 },
+    { 1730194207717538, 431790042319772, 1831515233279467, 1372080552768581, 1074513929381760 },
+    { 1450880638731607, 1019861580989005, 1229729455116861, 1174945729836143, 826083146840706 }
+  }
+},
+{ /* 20/31 */
+  {
+    { 1899935429242705, 1602068751520477, 940583196550370, 82431069053859, 1540863155745696 },
+    { 2136688454840028, 2099509000964294, 1690800495246475, 1217643678575476, 828720645084218 },
+    { 765548025667841, 462473984016099, 998061409979798, 546353034089527, 2212508972466858 }
+  },
+  {
+    { 46575283771160, 892570971573071, 1281983193144090, 1491520128287375, 75847005908304 },
+    { 1801436127943107, 1734436817907890, 1268728090345068, 167003097070711, 2233597765834956 },
+    { 1997562060465113, 1048700225534011, 7615603985628, 1855310849546841, 2242557647635213 }
+  },
+  {
+    { 1161017320376250, 492624580169043, 2169815802355237, 976496781732542, 1770879511019629 },
+    { 1357044908364776, 729130645262438, 1762469072918979, 1365633616878458, 181282906404941 },
+    { 1080413443139865, 1155205815510486, 1848782073549786, 622566975152580, 124965574467971 }
+  },
+  {
+    { 1184526762066993, 247622751762817, 692129017206356, 820018689412496, 2188697339828085 },
+    { 2020536369003019, 202261491735136, 1053169669150884, 2056531979272544, 778165514694311 },
+    { 237404399610207, 1308324858405118, 1229680749538400, 720131409105291, 1958958863624906 }
+  },
+  {
+    { 515583508038846, 17656978857189, 1717918437373989, 1568052070792483, 46975803123923 },
+    { 281527309158085, 36970532401524, 866906920877543, 2222282602952734, 1289598729589882 },
+    { 1278207464902042, 494742455008756, 1262082121427081, 1577236621659884, 1888786707293291 }
+  },
+  {
+    { 353042527954210, 1830056151907359, 1111731275799225, 174960955838824, 404312815582675 },
+    { 2064251142068628, 1666421603389706, 1419271365315441, 468767774902855, 191535130366583 },
+    { 1716987058588002, 1859366439773457, 1767194234188234, 64476199777924, 1117233614485261 }
+  },
+  {
+    { 984292135520292, 135138246951259, 2220652137473167, 1722843421165029, 190482558012909 },
+    { 298845952651262, 1166086588952562, 1179896526238434, 1347812759398693, 1412945390096208 },
+    { 1143239552672925, 906436640714209, 2177000572812152, 2075299936108548, 325186347798433 }
+  },
+  {
+    { 721024854374772, 684487861263316, 1373438744094159, 2193186935276995, 1387043709851261 },
+    { 418098668140962, 715065997721283, 1471916138376055, 2168570337288357, 937812682637044 },
+    { 1043584187226485, 2143395746619356, 2209558562919611, 482427979307092, 847556718384018 }
+  }
+},
+{ /* 21/31 */
+  {
+    { 1248731221520759, 1465200936117687, 540803492710140, 52978634680892, 261434490176109 },
+    { 1057329623869501, 620334067429122, 461700859268034, 2012481616501857, 297268569108938 },
+    { 1055352180870759, 1553151421852298, 1510903185371259, 1470458349428097, 1226259419062731 }
+  },
+  {
+    { 1492988790301668, 790326625573331, 1190107028409745, 1389394752159193, 1620408196604194 },
+    { 47000654413729, 1004754424173864, 1868044813557703, 173236934059409, 588771199737015 },
+    { 30498470091663, 1082245510489825, 576771653181956, 806509986132686, 1317634017056939 }
+  },
+  {
+    { 420308055751555, 1493354863316002, 165206721528088, 1884845694919786, 2065456951573059 },
+    { 1115636332012334, 1854340990964155, 83792697369514, 1972177451994021, 457455116057587 },
+    { 1698968457310898, 1435137169051090, 1083661677032510, 938363267483709, 340103887207182 }
+  },
+  {
+    { 1995325341336574, 911500251774648, 164010755403692, 855378419194762, 1573601397528842 },
+    { 241719380661528, 310028521317150, 1215881323380194, 1408214976493624, 2141142156467363 },
+    { 1315157046163473, 727368447885818, 1363466668108618, 1668921439990361, 1398483384337907 }
+  },
+  {
+    { 75029678299646, 1015388206460473, 1849729037055212, 1939814616452984, 444404230394954 },
+    { 2053597130993710, 2024431685856332, 2233550957004860, 2012407275509545, 872546993104440 },
+    { 1217269667678610, 599909351968693, 1390077048548598, 1471879360694802, 739586172317596 }
+  },
+  {
+    { 1718318639380794, 1560510726633958, 904462881159922, 1418028351780052, 94404349451937 },
+    { 2132502667405250, 214379346175414, 1502748313768060, 1960071701057800, 1353971822643138 },
+    { 319394212043702, 2127459436033571, 717646691535162, 663366796076914, 318459064945314 }
+  },
+  {
+    { 405989424923593, 1960452633787083, 667349034401665, 1492674260767112, 1451061489880787 },
+    { 947085906234007, 323284730494107, 1485778563977200, 728576821512394, 901584347702286 },
+    { 1575783124125742, 2126210792434375, 1569430791264065, 1402582372904727, 1891780248341114 }
+  },
+  {
+    { 838432205560695, 1997703511451664, 1018791879907867, 1662001808174331, 78328132957753 },
+    { 739152638255629, 2074935399403557, 505483666745895, 1611883356514088, 628654635394878 },
+    { 1822054032121349, 643057948186973, 7306757352712, 577249257962099, 284735863382083 }
+  }
+},
+{ /* 22/31 */
+  {
+    { 1366558556363930, 1448606567552086, 1478881020944768, 165803179355898, 1115718458123498 },
+    { 204146226972102, 1630511199034723, 2215235214174763, 174665910283542, 956127674017216 },
+    { 1562934578796716, 1070893489712745, 11324610642270, 958989751581897, 2172552325473805 }
+  },
+  {
+    { 1770564423056027, 735523631664565, 1326060113795289, 1509650369341127, 65892421582684 },
+    { 623682558650637, 1337866509471512, 990313350206649, 1314236615762469, 1164772974270275 },
+    { 223256821462517, 723690150104139, 1000261663630601, 933280913953265, 254872671543046 }
+  },
+  {
+    { 1969087237026041, 624795725447124, 1335555107635969, 2069986355593023, 1712100149341902 },
+    { 1236103475266979, 1837885883267218, 1026072585230455, 1025865513954973, 1801964901432134 },
+    { 1115241013365517, 1712251818829143, 2148864332502771, 2096001471438138, 2235017246626125 }
+  },
+  {
+    { 1299268198601632, 2047148477845621, 2165648650132450, 1612539282026145, 514197911628890 },
+    { 118352772338543, 1067608711804704, 1434796676193498, 1683240170548391, 230866769907437 },
+    { 1850689576796636, 1601590730430274, 1139674615958142, 1954384401440257, 76039205311 }
+  },
+  {
+    { 1723387471374172, 997301467038410, 533927635123657, 20928644693965, 1756575222802513 },
+    { 2146711623855116, 503278928021499, 625853062251406, 1109121378393107, 1033853809911861 },
+    { 571005965509422, 2005213373292546, 1016697270349626, 56607856974274, 914438579435146 }
+  },
+  {
+    { 1346698876211176, 2076651707527589, 1084761571110205, 265334478828406, 1068954492309671 },
+    { 1769967932677654, 1695893319756416, 1151863389675920, 1781042784397689, 400287774418285 },
+    { 1851867764003121, 403841933237558, 820549523771987, 761292590207581, 1743735048551143 }
+  },
+  {
+    { 410915148140008, 2107072311871739, 1004367461876503, 99684895396761, 1180818713503224 },
+    { 285945406881439, 648174397347453, 1098403762631981, 1366547441102991, 1505876883139217 },
+    { 672095903120153, 1675918957959872, 636236529315028, 1569297300327696, 2164144194785875 }
+  },
+  {
+    { 1902708175321798, 1035343530915438, 1178560808893263, 301095684058146, 1280977479761118 },
+    { 1615357281742403, 404257611616381, 2160201349780978, 1160947379188955, 1578038619549541 },
+    { 2013087639791217, 822734930507457, 1785668418619014, 1668650702946164, 389450875221715 }
+  }
+},
+{ /* 23/31 */
+  {
+    { 453918449698368, 106406819929001, 2072540975937135, 308588860670238, 1304394580755385 },
+    { 1295082798350326, 2091844511495996, 1851348972587817, 3375039684596, 789440738712837 },
+    { 2083069137186154, 848523102004566, 993982213589257, 1405313299916317, 1532824818698468 }
+  },
+  {
+    { 1495961298852430, 1397203457344779, 1774950217066942, 139302743555696, 66603584342787 },
+    { 1782411379088302, 1096724939964781, 27593390721418, 542241850291353, 1540337798439873 },
+    { 693543956581437, 171507720360750, 1557908942697227, 1074697073443438, 1104093109037196 }
+  },
+  {
+    { 345288228393419, 1099643569747172, 134881908403743, 1740551994106740, 248212179299770 },
+    { 231429562203065, 1526290236421172, 2021375064026423, 1520954495658041, 806337791525116 },
+    { 1079623667189886, 872403650198613, 766894200588288, 2163700860774109, 2023464507911816 }
+  },
+  {
+    { 854645372543796, 1936406001954827, 151460662541253, 825325739271555, 1554306377287556 },
+    { 1497138821904622, 1044820250515590, 1742593886423484, 1237204112746837, 849047450816987 },
+    { 667962773375330, 1897271816877105, 1399712621683474, 1143302161683099, 2081798441209593 }
+  },
+  {
+    { 127147851567005, 1936114012888110, 1704424366552046, 856674880716312, 716603621335359 },
+    { 1072409664800960, 2146937497077528, 1508780108920651, 935767602384853, 1112800433544068 },
+    { 333549023751292, 280219272863308, 2104176666454852, 1036466864875785, 536135186520207 }
+  },
+  {
+    { 373666279883137, 146457241530109, 304116267127857, 416088749147715, 1258577131183391 },
+    { 1186115062588401, 2251609796968486, 1098944457878953, 1153112761201374, 1791625503417267 },
+    { 1870078460219737, 2129630962183380, 852283639691142, 292865602592851, 401904317342226 }
+  },
+  {
+    { 1361070124828035, 815664541425524, 1026798897364671, 1951790935390647, 555874891834790 },
+    { 1546301003424277, 459094500062839, 1097668518375311, 1780297770129643, 720763293687608 },
+    { 1212405311403990, 1536693382542438, 61028431067459, 1863929423417129, 1223219538638038 }
+  },
+  {
+    { 1294303766540260, 1183557465955093, 882271357233093, 63854569425375, 2213283684565087 },
+    { 339050984211414, 601386726509773, 413735232134068, 966191255137228, 1839475899458159 },
+    { 235605972169408, 2174055643032978, 1538335001838863, 1281866796917192, 1815940222628465 }
+  }
+},
+{ /* 24/31 */
+  {
+    { 1632352921721536, 1833328609514701, 2092779091951987, 1923956201873226, 2210068022482919 },
+    { 35271216625062, 1712350667021807, 983664255668860, 98571260373038, 1232645608559836 },
+    { 1998172393429622, 1798947921427073, 784387737563581, 1589352214827263, 1589861734168180 }
+  },
+  {
+    { 1733739258725305, 31715717059538, 201969945218860, 992093044556990, 1194308773174556 },
+    { 846415389605137, 746163495539180, 829658752826080, 592067705956946, 957242537821393 },
+    { 1758148849754419, 619249044817679, 168089007997045, 1371497636330523, 1867101418880350 }
+  },
+  {
+    { 326633984209635, 261759506071016, 1700682323676193, 1577907266349064, 1217647663383016 },
+    { 1714182387328607, 1477856482074168, 574895689942184, 2159118410227270, 1555532449716575 },
+    { 853828206885131, 998498946036955, 1835887550391235, 207627336608048, 258363815956050 }
+  },
+  {
+    { 141141474651677, 1236728744905256, 643101419899887, 1646615130509173, 1208239602291765 },
+    { 1501663228068911, 1354879465566912, 1444432675498247, 897812463852601, 855062598754348 },
+    { 714380763546606, 1032824444965790, 1774073483745338, 1063840874947367, 1738680636537158 }
+  },
+  {
+    { 1640635546696252, 633168953192112, 2212651044092396, 30590958583852, 368515260889378 },
+    { 1171650314802029, 1567085444565577, 1453660792008405, 757914533009261, 1619511342778196 },
+    { 420958967093237, 971103481109486, 2169549185607107, 1301191633558497, 1661514101014240 }
+  },
+  {
+    { 907123651818302, 1332556122804146, 1824055253424487, 1367614217442959, 1982558335973172 },
+    { 1121533090144639, 1021251337022187, 110469995947421, 1511059774758394, 2110035908131662 },
+    { 303213233384524, 2061932261128138, 352862124777736, 40828818670255, 249879468482660 }
+  },
+  {
+    { 856559257852200, 508517664949010, 1378193767894916, 1723459126947129, 1962275756614521 },
+    { 1445691340537320, 40614383122127, 402104303144865, 485134269878232, 1659439323587426 },
+    { 20057458979482, 1183363722525800, 2140003847237215, 2053873950687614, 2112017736174909 }
+  },
+  {
+    { 2228654250927986, 1483591363415267, 1368661293910956, 1076511285177291, 526650682059608 },
+    { 709481497028540, 531682216165724, 316963769431931, 1814315888453765, 258560242424104 },
+    { 1053447823660455, 1955135194248683, 1010900954918985, 1182614026976701, 1240051576966610 }
+  }
+},
+{ /* 25/31 */
+  {
+    { 1957943897155497, 1788667368028035, 137692910029106, 1039519607062, 826404763313028 },
+    { 1848942433095597, 1582009882530495, 1849292741020143, 1068498323302788, 2001402229799484 },
+    { 1528282417624269, 2142492439828191, 2179662545816034, 362568973150328, 1591374675250271 }
+  },
+  {
+    { 160026679434388, 232341189218716, 2149181472355545, 598041771119831, 183859001910173 },
+    { 2013278155187349, 662660471354454, 793981225706267, 411706605985744, 804490933124791 },
+    { 2051892037280204, 488391251096321, 2230187337030708, 930221970662692, 679002758255210 }
+  },
+  {
+    { 1530723630438670, 875873929577927, 341560134269988, 449903119530753, 1055551308214179 },
+    { 1461835919309432, 1955256480136428, 180866187813063, 1551979252664528, 557743861963950 },
+    { 359179641731115, 1324915145732949, 902828372691474, 294254275669987, 1887036027752957 }
+  },
+  {
+    { 2043271609454323, 2038225437857464, 1317528426475850, 1398989128982787, 2027639881006861 },
+    { 2072902725256516, 312132452743412, 309930885642209, 996244312618453, 1590501300352303 },
+    { 1397254305160710, 695734355138021, 2233992044438756, 1776180593969996, 1085588199351115 }
+  },
+  {
+    { 440567051331029, 254894786356681, 493869224930222, 1556322069683366, 1567456540319218 },
+    { 1950722461391320, 1907845598854797, 1822757481635527, 2121567704750244, 73811931471221 },
+    { 387139307395758, 2058036430315676, 1220915649965325, 1794832055328951, 1230009312169328 }
+  },
+  {
+    { 1765973779329517, 659344059446977, 19821901606666, 1301928341311214, 1116266004075885 },
+    { 1127572801181483, 1224743760571696, 1276219889847274, 1529738721702581, 1589819666871853 },
+    { 2181229378964934, 2190885205260020, 1511536077659137, 1246504208580490, 668883326494241 }
+  },
+  {
+    { 437866655573314, 669026411194768, 81896997980338, 523874406393178, 245052060935236 },
+    { 1975438052228868, 1071801519999806, 594652299224319, 1877697652668809, 1489635366987285 },
+    { 958592545673770, 233048016518599, 851568750216589, 567703851596087, 1740300006094761 }
+  },
+  {
+    { 2014540178270324, 192672779514432, 213877182641530, 2194819933853411, 1716422829364835 },
+    { 1540769606609725, 2148289943846077, 1597804156127445, 1230603716683868, 815423458809453 },
+    { 1738560251245018, 1779576754536888, 1783765347671392, 1880170990446751, 1088225159617541 }
+  }
+},
+{ /* 26/31 */
+  {
+    { 659303913929492, 1956447718227573, 1830568515922666, 841069049744408, 1669607124206368 },
+    { 1143465490433355, 1532194726196059, 1093276745494697, 481041706116088, 2121405433561163 },
+    { 1686424298744462, 1451806974487153, 266296068846582, 1834686947542675, 1720762336132256 }
+  },
+  {
+    { 889217026388959, 1043290623284660, 856125087551909, 1669272323124636, 1603340330827879 },
+    { 1206396181488998, 333158148435054, 1402633492821422, 1120091191722026, 1945474114550509 },
+    { 766720088232571, 1512222781191002, 1189719893490790, 2091302129467914, 2141418006894941 }
+  },
+  {
+    { 419663647306612, 1998875112167987, 1426599870253707, 1154928355379510, 486538532138187 },
+    { 938160078005954, 1421776319053174, 1941643234741774, 180002183320818, 1414380336750546 },
+    { 398001940109652, 1577721237663248, 1012748649830402, 1540516006905144, 1011684812884559 }
+  },
+  {
+    { 1653276489969630, 6081825167624, 1921777941170836, 1604139841794531, 861211053640641 },
+    { 996661541407379, 1455877387952927, 744312806857277, 139213896196746, 1000282908547789 },
+    { 1450817495603008, 1476865707053229, 1030490562252053, 620966950353376, 1744760161539058 }
+  },
+  {
+    { 559728410002599, 37056661641185, 2038622963352006, 1637244893271723, 1026565352238948 },
+    { 962165956135846, 1116599660248791, 182090178006815, 1455605467021751, 196053588803284 },
+    { 796863823080135, 1897365583584155, 420466939481601, 2165972651724672, 932177357788289 }
+  },
+  {
+    { 877047233620632, 1375632631944375, 643773611882121, 660022738847877, 19353932331831 },
+    { 2216943882299338, 394841323190322, 2222656898319671, 558186553950529, 1077236877025190 },
+    { 801118384953213, 1914330175515892, 574541023311511, 1471123787903705, 1526158900256288 }
+  },
+  {
+    { 949617889087234, 2207116611267331, 912920039141287, 501158539198789, 62362560771472 },
+    { 1474518386765335, 1760793622169197, 1157399790472736, 1622864308058898, 165428294422792 },
+    { 1961673048027128, 102619413083113, 1051982726768458, 1603657989805485, 1941613251499678 }
+  },
+  {
+    { 1401939116319266, 335306339903072, 72046196085786, 862423201496006, 850518754531384 },
+    { 1234706593321979, 1083343891215917, 898273974314935, 1640859118399498, 157578398571149 },
+    { 1143483057726416, 1992614991758919, 674268662140796, 1773370048077526, 674318359920189 }
+  }
+},
+{ /* 27/31 */
+  {
+    { 1835401379538542, 173900035308392, 818247630716732, 1762100412152786, 1021506399448291 },
+    { 1506632088156630, 2127481795522179, 513812919490255, 140643715928370, 442476620300318 },
+    { 2056683376856736, 219094741662735, 2193541883188309, 1841182310235800, 556477468664293 }
+  },
+  {
+    { 1315019427910827, 1049075855992603, 2066573052986543, 266904467185534, 2040482348591520 },
+    { 94096246544434, 922482381166992, 24517828745563, 2139430508542503, 2097139044231004 },
+    { 537697207950515, 1399352016347350, 1563663552106345, 2148749520888918, 549922092988516 }
+  },
+  {
+    { 1747985413252434, 680511052635695, 1809559829982725, 594274250930054, 201673170745982 },
+    { 323583936109569, 1973572998577657, 1192219029966558, 79354804385273, 1374043025560347 },
+    { 213277331329947, 416202017849623, 1950535221091783, 1313441578103244, 2171386783823658 }
+  },
+  {
+    { 189088804229831, 993969372859110, 895870121536987, 1547301535298256, 1477373024911350 },
+    { 1620578418245010, 541035331188469, 2235785724453865, 2154865809088198, 1974627268751826 },
+    { 1346805451740245, 1350981335690626, 942744349501813, 2155094562545502, 1012483751693409 }
+  },
+  {
+    { 2107080134091762, 1132567062788208, 1824935377687210, 769194804343737, 1857941799971888 },
+    { 1074666112436467, 249279386739593, 1174337926625354, 1559013532006480, 1472287775519121 },
+    { 1872620123779532, 1892932666768992, 1921559078394978, 1270573311796160, 1438913646755037 }
+  },
+  {
+    { 837390187648199, 1012253300223599, 989780015893987, 1351393287739814, 328627746545550 },
+    { 1028328827183114, 1711043289969857, 1350832470374933, 1923164689604327, 1495656368846911 },
+    { 1900828492104143, 430212361082163, 687437570852799, 832514536673512, 1685641495940794 }
+  },
+  {
+    { 842632847936398, 605670026766216, 290836444839585, 163210774892356, 2213815011799645 },
+    { 1176336383453996, 1725477294339771, 12700622672454, 678015708818208, 162724078519879 },
+    { 1448049969043497, 1789411762943521, 385587766217753, 90201620913498, 832999441066823 }
+  },
+  {
+    { 516086333293313, 2240508292484616, 1351669528166508, 1223255565316488, 750235824427138 },
+    { 1263624896582495, 1102602401673328, 526302183714372, 2152015839128799, 1483839308490010 },
+    { 442991718646863, 1599275157036458, 1925389027579192, 899514691371390, 350263251085160 }
+  }
+},
+{ /* 28/31 */
+  {
+    { 1689713572022143, 593854559254373, 978095044791970, 1985127338729499, 1676069120347625 },
+    { 1557207018622683, 340631692799603, 1477725909476187, 614735951619419, 2033237123746766 },
+    { 968764929340557, 1225534776710944, 662967304013036, 1155521416178595, 791142883466590 }
+  },
+  {
+    { 1487081286167458, 993039441814934, 1792378982844640, 698652444999874, 2153908693179754 },
+    { 1123181311102823, 685575944875442, 507605465509927, 1412590462117473, 568017325228626 },
+    { 560258797465417, 2193971151466401, 1824086900849026, 579056363542056, 1690063960036441 }
+  },
+  {
+    { 1918407319222416, 353767553059963, 1930426334528099, 1564816146005724, 1861342381708096 },
+    { 2131325168777276, 1176636658428908, 1756922641512981, 1390243617176012, 1966325177038383 },
+    { 2063958120364491, 2140267332393533, 699896251574968, 273268351312140, 375580724713232 }
+  },
+  {
+    { 2024297515263178, 416959329722687, 1079014235017302, 171612225573183, 1031677520051053 },
+    { 2033900009388450, 1744902869870788, 2190580087917640, 1949474984254121, 231049754293748 },
+    { 343868674606581, 550155864008088, 1450580864229630, 481603765195050, 896972360018042 }
+  },
+  {
+    { 2151139328380127, 314745882084928, 59756825775204, 1676664391494651, 2048348075599360 },
+    { 1528930066340597, 1605003907059576, 1055061081337675, 1458319101947665, 1234195845213142 },
+    { 830430507734812, 1780282976102377, 1425386760709037, 362399353095425, 2168861579799910 }
+  },
+  {
+    { 1155762232730333, 980662895504006, 2053766700883521, 490966214077606, 510405877041357 },
+    { 1683750316716132, 652278688286128, 1221798761193539, 1897360681476669, 319658166027343 },
+    { 618808732869972, 72755186759744, 2060379135624181, 1730731526741822, 48862757828238 }
+  },
+  {
+    { 1463171970593505, 1143040711767452, 614590986558883, 1409210575145591, 1882816996436803 },
+    { 2230133264691131, 563950955091024, 2042915975426398, 827314356293472, 672028980152815 },
+    { 264204366029760, 1654686424479449, 2185050199932931, 2207056159091748, 506015669043634 }
+  },
+  {
+    { 1784446333136569, 1973746527984364, 334856327359575, 1156769775884610, 1023950124675478 },
+    { 2065270940578383, 31477096270353, 306421879113491, 181958643936686, 1907105536686083 },
+    { 1496516440779464, 1748485652986458, 872778352227340, 818358834654919, 97932669284220 }
+  }
+},
+{ /* 29/31 */
+  {
+    { 471636015770351, 672455402793577, 1804995246884103, 1842309243470804, 1501862504981682 },
+    { 1013216974933691, 538921919682598, 1915776722521558, 1742822441583877, 1886550687916656 },
+    { 2094270000643336, 303971879192276, 40801275554748, 649448917027930, 1818544418535447 }
+  },
+  {
+    { 2241737709499165, 549397817447461, 838180519319392, 1725686958520781, 1705639080897747 },
+    { 1216074541925116, 50120933933509, 1565829004133810, 721728156134580, 349206064666188 },
+    { 948617110470858, 346222547451945, 1126511960599975, 1759386906004538, 493053284802266 }
+  },
+  {
+    { 1454933046815146, 874696014266362, 1467170975468588, 1432316382418897, 2111710746366763 },
+    { 2105387117364450, 1996463405126433, 1303008614294500, 851908115948209, 1353742049788635 },
+    { 750300956351719, 1487736556065813, 15158817002104, 1511998221598392, 971739901354129 }
+  },
+  {
+    { 1874648163531693, 2124487685930551, 1810030029384882, 918400043048335, 586348627300650 },
+    { 1235084464747900, 1166111146432082, 1745394857881591, 1405516473883040, 4463504151617 },
+    { 1663810156463827, 327797390285791, 1341846161759410, 1964121122800605, 1747470312055380 }
+  },
+  {
+    { 660005247548233, 2071860029952887, 1358748199950107, 911703252219107, 1014379923023831 },
+    { 2206641276178231, 1690587809721504, 1600173622825126, 2156096097634421, 1106822408548216 },
+    { 1344788193552206, 1949552134239140, 1735915881729557, 675891104100469, 1834220014427292 }
+  },
+  {
+    { 1920949492387964, 158885288387530, 70308263664033, 626038464897817, 1468081726101009 },
+    { 622221042073383, 1210146474039168, 1742246422343683, 1403839361379025, 417189490895736 },
+    { 22727256592983, 168471543384997, 1324340989803650, 1839310709638189, 504999476432775 }
+  },
+  {
+    { 1313240518756327, 1721896294296942, 52263574587266, 2065069734239232, 804910473424630 },
+    { 1337466662091884, 1287645354669772, 2018019646776184, 652181229374245, 898011753211715 },
+    { 1969792547910734, 779969968247557, 2011350094423418, 1823964252907487, 1058949448296945 }
+  },
+  {
+    { 207343737062002, 1118176942430253, 758894594548164, 806764629546266, 1157700123092949 },
+    { 1273565321399022, 1638509681964574, 759235866488935, 666015124346707, 897983460943405 },
+    { 1717263794012298, 1059601762860786, 1837819172257618, 1054130665797229, 680893204263559 }
+  }
+},
+{ /* 30/31 */
+  {
+    { 2237039662793603, 2249022333361206, 2058613546633703, 149454094845279, 2215176649164582 },
+    { 79472182719605, 1851130257050174, 1825744808933107, 821667333481068, 781795293511946 },
+    { 755822026485370, 152464789723500, 1178207602290608, 410307889503239, 156581253571278 }
+  },
+  {
+    { 1418185496130297, 484520167728613, 1646737281442950, 1401487684670265, 1349185550126961 },
+    { 1495380034400429, 325049476417173, 46346894893933, 1553408840354856, 828980101835683 },
+    { 1280337889310282, 2070832742866672, 1640940617225222, 2098284908289951, 450929509534434 }
+  },
+  {
+    { 407703353998781, 126572141483652, 286039827513621, 1999255076709338, 2030511179441770 },
+    { 1254958221100483, 1153235960999843, 942907704968834, 637105404087392, 1149293270147267 },
+    { 894249020470196, 400291701616810, 406878712230981, 1599128793487393, 1145868722604026 }
+  },
+  {
+    { 1497955250203334, 110116344653260, 1128535642171976, 1900106496009660, 129792717460909 },
+    { 452487513298665, 1352120549024569, 1173495883910956, 1999111705922009, 367328130454226 },
+    { 1717539401269642, 1475188995688487, 891921989653942, 836824441505699, 1885988485608364 }
+  },
+  {
+    { 1241784121422547, 187337051947583, 1118481812236193, 428747751936362, 30358898927325 },
+    { 2022432361201842, 1088816090685051, 1977843398539868, 1854834215890724, 564238862029357 },
+    { 938868489100585, 1100285072929025, 1017806255688848, 1957262154788833, 152787950560442 }
+  },
+  {
+    { 867319417678923, 620471962942542, 226032203305716, 342001443957629, 1761675818237336 },
+    { 1295072362439987, 931227904689414, 1355731432641687, 922235735834035, 892227229410209 },
+    { 1680989767906154, 535362787031440, 2136691276706570, 1942228485381244, 1267350086882274 }
+  },
+  {
+    { 366018233770527, 432660629755596, 126409707644535, 1973842949591662, 645627343442376 },
+    { 535509430575217, 546885533737322, 1524675609547799, 2138095752851703, 1260738089896827 },
+    { 1159906385590467, 2198530004321610, 714559485023225, 81880727882151, 1484020820037082 }
+  },
+  {
+    { 1377485731340769, 2046328105512000, 1802058637158797, 62146136768173, 1356993908853901 },
+    { 2013612215646735, 1830770575920375, 536135310219832, 609272325580394, 270684344495013 },
+    { 1237542585982777, 2228682050256790, 1385281931622824, 593183794882890, 493654978552689 }
+  }
+},
+{ /* 31/31 */
+  {
+    { 47341488007760, 1891414891220257, 983894663308928, 176161768286818, 1126261115179708 },
+    { 1694030170963455, 502038567066200, 1691160065225467, 949628319562187, 275110186693066 },
+    { 1124515748676336, 1661673816593408, 1499640319059718, 1584929449166988, 558148594103306 }
+  },
+  {
+    { 1784525599998356, 1619698033617383, 2097300287550715, 258265458103756, 1905684794832758 },
+    { 1288941072872766, 931787902039402, 190731008859042, 2006859954667190, 1005931482221702 },
+    { 1465551264822703, 152905080555927, 680334307368453, 173227184634745, 666407097159852 }
+  },
+  {
+    { 2111017076203943, 1378760485794347, 1248583954016456, 1352289194864422, 1895180776543896 },
+    { 171348223915638, 662766099800389, 462338943760497, 466917763340314, 656911292869115 },
+    { 488623681976577, 866497561541722, 1708105560937768, 1673781214218839, 1506146329818807 }
+  },
+  {
+    { 160425464456957, 950394373239689, 430497123340934, 711676555398832, 320964687779005 },
+    { 988979367990485, 1359729327576302, 1301834257246029, 294141160829308, 29348272277475 },
+    { 1434382743317910, 100082049942065, 221102347892623, 186982837860588, 1305765053501834 }
+  },
+  {
+    { 2205916462268190, 499863829790820, 961960554686616, 158062762756985, 1841471168298305 },
+    { 1191737341426592, 1847042034978363, 1382213545049056, 1039952395710448, 788812858896859 },
+    { 1346965964571152, 1291881610839830, 2142916164336056, 786821641205979, 1571709146321039 }
+  },
+  {
+    { 787164375951248, 202869205373189, 1356590421032140, 1431233331032510, 786341368775957 },
+    { 492448143532951, 304105152670757, 1761767168301056, 233782684697790, 1981295323106089 },
+    { 665807507761866, 1343384868355425, 895831046139653, 439338948736892, 1986828765695105 }
+  },
+  {
+    { 756096210874553, 1721699973539149, 258765301727885, 1390588532210645, 1212530909934781 },
+    { 852891097972275, 1816988871354562, 1543772755726524, 1174710635522444, 202129090724628 },
+    { 1205281565824323, 22430498399418, 992947814485516, 1392458699738672, 688441466734558 }
+  },
+  {
+    { 1050627428414972, 1955849529137135, 2171162376368357, 91745868298214, 447733118757826 },
+    { 1287181461435438, 622722465530711, 880952150571872, 741035693459198, 311565274989772 },
+    { 1003649078149734, 545233927396469, 1849786171789880, 1318943684880434, 280345687170552 }
+  }
+}

+ 40 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_51/base2.h

@@ -0,0 +1,40 @@
+{
+  { 1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563 },
+  { 62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585 },
+  { 301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142 }
+},
+{
+  { 1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911 },
+  { 316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597 },
+  { 1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707 }
+},
+{
+  { 769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016 },
+  { 425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893 },
+  { 1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339 }
+},
+{
+  { 665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985 },
+  { 2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113 },
+  { 965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601 }
+},
+{
+  { 1802695059465007, 1664899123557221, 593559490740857, 2160434469266659, 927570450755031 },
+  { 1725674970513508, 1933645953859181, 1542344539275782, 1767788773573747, 1297447965928905 },
+  { 1381809363726107, 1430341051343062, 2061843536018959, 1551778050872521, 2036394857967624 }
+},
+{
+  { 1970894096313054, 528066325833207, 1619374932191227, 2207306624415883, 1169170329061080 },
+  { 2070390218572616, 1458919061857835, 624171843017421, 1055332792707765, 433987520732508 },
+  { 893653801273833, 1168026499324677, 1242553501121234, 1306366254304474, 1086752658510815 }
+},
+{
+  { 213454002618221, 939771523987438, 1159882208056014, 317388369627517, 621213314200687 },
+  { 1971678598905747, 338026507889165, 762398079972271, 655096486107477, 42299032696322 },
+  { 177130678690680, 1754759263300204, 1864311296286618, 1180675631479880, 1292726903152791 }
+},
+{
+  { 1913163449625248, 460779200291993, 2193883288642314, 1008900146920800, 1721983679009502 },
+  { 1070401523076875, 1272492007800961, 1910153608563310, 2075579521696771, 1191169788841221 },
+  { 692896803108118, 500174642072499, 2068223309439677, 1162190621851337, 1426986007309901 }
+}

+ 41 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_51/constants.h

@@ -0,0 +1,41 @@
+/* 37095705934669439343138083508754565189542113879843219016388785533085940283555 */
+static const fe25519 d = {
+    929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575
+};
+
+/* 2 * d =
+ * 16295367250680780974490674513165176452449235426866156013048779062215315747161
+ */
+static const fe25519 d2 = {
+    1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903
+};
+
+/* sqrt(-1) */
+static const fe25519 sqrtm1 = {
+    1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133
+};
+
+/* A = 486662 */
+static const fe25519 curve25519_A = {
+    486662, 0, 0, 0, 0
+};
+
+/* sqrt(ad - 1) with a = -1 (mod p) */
+static const fe25519 sqrtadm1 = {
+    2241493124984347, 425987919032274, 2207028919301688, 1220490630685848, 974799131293748
+};
+
+/* 1 / sqrt(a - d) */
+static const fe25519 invsqrtamd = {
+    278908739862762, 821645201101625, 8113234426968, 1777959178193151, 2118520810568447
+};
+
+/* 1 - d ^ 2 */
+static const fe25519 onemsqd = {
+    1136626929484150, 1998550399581263, 496427632559748, 118527312129759, 45110755273534
+};
+
+/* (d - 1) ^ 2 */
+static const fe25519 sqdmone = {
+    1507062230895904, 1572317787530805, 683053064812840, 317374165784489, 1572899562415810
+};

+ 116 - 0
Sources/Sodium/crypto_core/ed25519/ref10/fe_51/fe.h

@@ -0,0 +1,116 @@
+/*
+ Ignores top bit of h.
+ */
+
+void
+fe25519_frombytes(fe25519 h, const unsigned char *s)
+{
+    const uint64_t mask = 0x7ffffffffffffULL;
+    uint64_t h0, h1, h2, h3, h4;
+
+    h0 = (LOAD64_LE(s     )      ) & mask;
+    h1 = (LOAD64_LE(s +  6) >>  3) & mask;
+    h2 = (LOAD64_LE(s + 12) >>  6) & mask;
+    h3 = (LOAD64_LE(s + 19) >>  1) & mask;
+    h4 = (LOAD64_LE(s + 24) >> 12) & mask;
+
+    h[0] = h0;
+    h[1] = h1;
+    h[2] = h2;
+    h[3] = h3;
+    h[4] = h4;
+}
+
+static void
+fe25519_reduce(fe25519 h, const fe25519 f)
+{
+    const uint64_t mask = 0x7ffffffffffffULL;
+    uint128_t t[5];
+
+    t[0] = f[0];
+    t[1] = f[1];
+    t[2] = f[2];
+    t[3] = f[3];
+    t[4] = f[4];
+
+    t[1] += t[0] >> 51;
+    t[0] &= mask;
+    t[2] += t[1] >> 51;
+    t[1] &= mask;
+    t[3] += t[2] >> 51;
+    t[2] &= mask;
+    t[4] += t[3] >> 51;
+    t[3] &= mask;
+    t[0] += 19 * (t[4] >> 51);
+    t[4] &= mask;
+
+    t[1] += t[0] >> 51;
+    t[0] &= mask;
+    t[2] += t[1] >> 51;
+    t[1] &= mask;
+    t[3] += t[2] >> 51;
+    t[2] &= mask;
+    t[4] += t[3] >> 51;
+    t[3] &= mask;
+    t[0] += 19 * (t[4] >> 51);
+    t[4] &= mask;
+
+    /* now t is between 0 and 2^255-1, properly carried. */
+    /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
+
+    t[0] += 19ULL;
+
+    t[1] += t[0] >> 51;
+    t[0] &= mask;
+    t[2] += t[1] >> 51;
+    t[1] &= mask;
+    t[3] += t[2] >> 51;
+    t[2] &= mask;
+    t[4] += t[3] >> 51;
+    t[3] &= mask;
+    t[0] += 19ULL * (t[4] >> 51);
+    t[4] &= mask;
+
+    /* now between 19 and 2^255-1 in both cases, and offset by 19. */
+
+    t[0] += 0x8000000000000 - 19ULL;
+    t[1] += 0x8000000000000 - 1ULL;
+    t[2] += 0x8000000000000 - 1ULL;
+    t[3] += 0x8000000000000 - 1ULL;
+    t[4] += 0x8000000000000 - 1ULL;
+
+    /* now between 2^255 and 2^256-20, and offset by 2^255. */
+
+    t[1] += t[0] >> 51;
+    t[0] &= mask;
+    t[2] += t[1] >> 51;
+    t[1] &= mask;
+    t[3] += t[2] >> 51;
+    t[2] &= mask;
+    t[4] += t[3] >> 51;
+    t[3] &= mask;
+    t[4] &= mask;
+
+    h[0] = t[0];
+    h[1] = t[1];
+    h[2] = t[2];
+    h[3] = t[3];
+    h[4] = t[4];
+}
+
+void
+fe25519_tobytes(unsigned char *s, const fe25519 h)
+{
+    fe25519  t;
+    uint64_t t0, t1, t2, t3;
+
+    fe25519_reduce(t, h);
+    t0 = t[0] | (t[1] << 51);
+    t1 = (t[1] >> 13) | (t[2] << 38);
+    t2 = (t[2] >> 26) | (t[3] << 25);
+    t3 = (t[3] >> 39) | (t[4] << 12);
+    STORE64_LE(s +  0, t0);
+    STORE64_LE(s +  8, t1);
+    STORE64_LE(s + 16, t2);
+    STORE64_LE(s + 24, t3);
+}

+ 93 - 0
Sources/Sodium/crypto_core/hchacha20/core_hchacha20.c

@@ -0,0 +1,93 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crypto_core_hchacha20.h"
+#include "private/common.h"
+
+#define QUARTERROUND(A, B, C, D)     \
+  do {                               \
+      A += B; D = ROTL32(D ^ A, 16); \
+      C += D; B = ROTL32(B ^ C, 12); \
+      A += B; D = ROTL32(D ^ A,  8); \
+      C += D; B = ROTL32(B ^ C,  7); \
+  } while(0)
+
+int
+crypto_core_hchacha20(unsigned char *out, const unsigned char *in,
+                      const unsigned char *k, const unsigned char *c)
+{
+    int      i;
+    uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+    uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
+
+    if (c == NULL) {
+        x0 = 0x61707865;
+        x1 = 0x3320646e;
+        x2 = 0x79622d32;
+        x3 = 0x6b206574;
+    } else {
+        x0 = LOAD32_LE(c +  0);
+        x1 = LOAD32_LE(c +  4);
+        x2 = LOAD32_LE(c +  8);
+        x3 = LOAD32_LE(c + 12);
+    }
+    x4  = LOAD32_LE(k +  0);
+    x5  = LOAD32_LE(k +  4);
+    x6  = LOAD32_LE(k +  8);
+    x7  = LOAD32_LE(k + 12);
+    x8  = LOAD32_LE(k + 16);
+    x9  = LOAD32_LE(k + 20);
+    x10 = LOAD32_LE(k + 24);
+    x11 = LOAD32_LE(k + 28);
+    x12 = LOAD32_LE(in +  0);
+    x13 = LOAD32_LE(in +  4);
+    x14 = LOAD32_LE(in +  8);
+    x15 = LOAD32_LE(in + 12);
+
+    for (i = 0; i < 10; i++) {
+        QUARTERROUND(x0, x4,  x8, x12);
+        QUARTERROUND(x1, x5,  x9, x13);
+        QUARTERROUND(x2, x6, x10, x14);
+        QUARTERROUND(x3, x7, x11, x15);
+        QUARTERROUND(x0, x5, x10, x15);
+        QUARTERROUND(x1, x6, x11, x12);
+        QUARTERROUND(x2, x7,  x8, x13);
+        QUARTERROUND(x3, x4,  x9, x14);
+    }
+
+    STORE32_LE(out +  0, x0);
+    STORE32_LE(out +  4, x1);
+    STORE32_LE(out +  8, x2);
+    STORE32_LE(out + 12, x3);
+    STORE32_LE(out + 16, x12);
+    STORE32_LE(out + 20, x13);
+    STORE32_LE(out + 24, x14);
+    STORE32_LE(out + 28, x15);
+
+    return 0;
+}
+
+size_t
+crypto_core_hchacha20_outputbytes(void)
+{
+    return crypto_core_hchacha20_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_hchacha20_inputbytes(void)
+{
+    return crypto_core_hchacha20_INPUTBYTES;
+}
+
+size_t
+crypto_core_hchacha20_keybytes(void)
+{
+    return crypto_core_hchacha20_KEYBYTES;
+}
+
+size_t
+crypto_core_hchacha20_constbytes(void)
+{
+    return crypto_core_hchacha20_CONSTBYTES;
+}

+ 21 - 0
Sources/Sodium/crypto_core/hsalsa20/core_hsalsa20.c

@@ -0,0 +1,21 @@
+#include "crypto_core_hsalsa20.h"
+
+size_t
+crypto_core_hsalsa20_outputbytes(void) {
+    return crypto_core_hsalsa20_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_hsalsa20_inputbytes(void) {
+    return crypto_core_hsalsa20_INPUTBYTES;
+}
+
+size_t
+crypto_core_hsalsa20_keybytes(void) {
+    return crypto_core_hsalsa20_KEYBYTES;
+}
+
+size_t
+crypto_core_hsalsa20_constbytes(void) {
+    return crypto_core_hsalsa20_CONSTBYTES;
+}

+ 95 - 0
Sources/Sodium/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c

@@ -0,0 +1,95 @@
+/*
+version 20080912
+D. J. Bernstein
+Public domain.
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crypto_core_hsalsa20.h"
+#include "private/common.h"
+
+#define ROUNDS 20
+#define U32C(v) (v##U)
+
+int
+crypto_core_hsalsa20(unsigned char *out,
+                     const unsigned char *in,
+                     const unsigned char *k,
+                     const unsigned char *c)
+{
+    uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8,
+             x9, x10, x11, x12, x13, x14,  x15;
+    int      i;
+
+    if (c == NULL) {
+        x0 = U32C(0x61707865);
+        x5 = U32C(0x3320646e);
+        x10 = U32C(0x79622d32);
+        x15 = U32C(0x6b206574);
+    } else {
+        x0 = LOAD32_LE(c + 0);
+        x5 = LOAD32_LE(c + 4);
+        x10 = LOAD32_LE(c + 8);
+        x15 = LOAD32_LE(c + 12);
+    }
+    x1 = LOAD32_LE(k + 0);
+    x2 = LOAD32_LE(k + 4);
+    x3 = LOAD32_LE(k + 8);
+    x4 = LOAD32_LE(k + 12);
+    x11 = LOAD32_LE(k + 16);
+    x12 = LOAD32_LE(k + 20);
+    x13 = LOAD32_LE(k + 24);
+    x14 = LOAD32_LE(k + 28);
+    x6 = LOAD32_LE(in + 0);
+    x7 = LOAD32_LE(in + 4);
+    x8 = LOAD32_LE(in + 8);
+    x9 = LOAD32_LE(in + 12);
+
+    for (i = ROUNDS; i > 0; i -= 2) {
+        x4 ^= ROTL32(x0 + x12, 7);
+        x8 ^= ROTL32(x4 + x0, 9);
+        x12 ^= ROTL32(x8 + x4, 13);
+        x0 ^= ROTL32(x12 + x8, 18);
+        x9 ^= ROTL32(x5 + x1, 7);
+        x13 ^= ROTL32(x9 + x5, 9);
+        x1 ^= ROTL32(x13 + x9, 13);
+        x5 ^= ROTL32(x1 + x13, 18);
+        x14 ^= ROTL32(x10 + x6, 7);
+        x2 ^= ROTL32(x14 + x10, 9);
+        x6 ^= ROTL32(x2 + x14, 13);
+        x10 ^= ROTL32(x6 + x2, 18);
+        x3 ^= ROTL32(x15 + x11, 7);
+        x7 ^= ROTL32(x3 + x15, 9);
+        x11 ^= ROTL32(x7 + x3, 13);
+        x15 ^= ROTL32(x11 + x7, 18);
+        x1 ^= ROTL32(x0 + x3, 7);
+        x2 ^= ROTL32(x1 + x0, 9);
+        x3 ^= ROTL32(x2 + x1, 13);
+        x0 ^= ROTL32(x3 + x2, 18);
+        x6 ^= ROTL32(x5 + x4, 7);
+        x7 ^= ROTL32(x6 + x5, 9);
+        x4 ^= ROTL32(x7 + x6, 13);
+        x5 ^= ROTL32(x4 + x7, 18);
+        x11 ^= ROTL32(x10 + x9, 7);
+        x8 ^= ROTL32(x11 + x10, 9);
+        x9 ^= ROTL32(x8 + x11, 13);
+        x10 ^= ROTL32(x9 + x8, 18);
+        x12 ^= ROTL32(x15 + x14, 7);
+        x13 ^= ROTL32(x12 + x15, 9);
+        x14 ^= ROTL32(x13 + x12, 13);
+        x15 ^= ROTL32(x14 + x13, 18);
+    }
+
+    STORE32_LE(out + 0, x0);
+    STORE32_LE(out + 4, x5);
+    STORE32_LE(out + 8, x10);
+    STORE32_LE(out + 12, x15);
+    STORE32_LE(out + 16, x6);
+    STORE32_LE(out + 20, x7);
+    STORE32_LE(out + 24, x8);
+    STORE32_LE(out + 28, x9);
+
+    return 0;
+}

+ 195 - 0
Sources/Sodium/crypto_core/salsa/ref/core_salsa_ref.c

@@ -0,0 +1,195 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crypto_core_salsa20.h"
+#include "crypto_core_salsa2012.h"
+#include "crypto_core_salsa208.h"
+#include "private/common.h"
+
+static void
+crypto_core_salsa(unsigned char *out, const unsigned char *in,
+                  const unsigned char *k, const unsigned char *c,
+                  const int rounds)
+{
+    uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
+        x15;
+    uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14,
+        j15;
+    int i;
+
+    j0  = x0  = 0x61707865;
+    j5  = x5  = 0x3320646e;
+    j10 = x10 = 0x79622d32;
+    j15 = x15 = 0x6b206574;
+    if (c != NULL) {
+        j0  = x0  = LOAD32_LE(c + 0);
+        j5  = x5  = LOAD32_LE(c + 4);
+        j10 = x10 = LOAD32_LE(c + 8);
+        j15 = x15 = LOAD32_LE(c + 12);
+    }
+    j1  = x1  = LOAD32_LE(k + 0);
+    j2  = x2  = LOAD32_LE(k + 4);
+    j3  = x3  = LOAD32_LE(k + 8);
+    j4  = x4  = LOAD32_LE(k + 12);
+    j11 = x11 = LOAD32_LE(k + 16);
+    j12 = x12 = LOAD32_LE(k + 20);
+    j13 = x13 = LOAD32_LE(k + 24);
+    j14 = x14 = LOAD32_LE(k + 28);
+
+    j6  = x6  = LOAD32_LE(in + 0);
+    j7  = x7  = LOAD32_LE(in + 4);
+    j8  = x8  = LOAD32_LE(in + 8);
+    j9  = x9  = LOAD32_LE(in + 12);
+
+    for (i = 0; i < rounds; i += 2) {
+        x4  ^= ROTL32(x0  + x12, 7);
+        x8  ^= ROTL32(x4  + x0, 9);
+        x12 ^= ROTL32(x8  + x4, 13);
+        x0  ^= ROTL32(x12 + x8, 18);
+        x9  ^= ROTL32(x5  + x1, 7);
+        x13 ^= ROTL32(x9  + x5, 9);
+        x1  ^= ROTL32(x13 + x9, 13);
+        x5  ^= ROTL32(x1  + x13, 18);
+        x14 ^= ROTL32(x10 + x6, 7);
+        x2  ^= ROTL32(x14 + x10, 9);
+        x6  ^= ROTL32(x2  + x14, 13);
+        x10 ^= ROTL32(x6  + x2, 18);
+        x3  ^= ROTL32(x15 + x11, 7);
+        x7  ^= ROTL32(x3  + x15, 9);
+        x11 ^= ROTL32(x7  + x3, 13);
+        x15 ^= ROTL32(x11 + x7, 18);
+        x1  ^= ROTL32(x0  + x3, 7);
+        x2  ^= ROTL32(x1  + x0, 9);
+        x3  ^= ROTL32(x2  + x1, 13);
+        x0  ^= ROTL32(x3  + x2, 18);
+        x6  ^= ROTL32(x5  + x4, 7);
+        x7  ^= ROTL32(x6  + x5, 9);
+        x4  ^= ROTL32(x7  + x6, 13);
+        x5  ^= ROTL32(x4  + x7, 18);
+        x11 ^= ROTL32(x10 + x9, 7);
+        x8  ^= ROTL32(x11 + x10, 9);
+        x9  ^= ROTL32(x8  + x11, 13);
+        x10 ^= ROTL32(x9  + x8, 18);
+        x12 ^= ROTL32(x15 + x14, 7);
+        x13 ^= ROTL32(x12 + x15, 9);
+        x14 ^= ROTL32(x13 + x12, 13);
+        x15 ^= ROTL32(x14 + x13, 18);
+    }
+    STORE32_LE(out + 0,  x0  + j0);
+    STORE32_LE(out + 4,  x1  + j1);
+    STORE32_LE(out + 8,  x2  + j2);
+    STORE32_LE(out + 12, x3  + j3);
+    STORE32_LE(out + 16, x4  + j4);
+    STORE32_LE(out + 20, x5  + j5);
+    STORE32_LE(out + 24, x6  + j6);
+    STORE32_LE(out + 28, x7  + j7);
+    STORE32_LE(out + 32, x8  + j8);
+    STORE32_LE(out + 36, x9  + j9);
+    STORE32_LE(out + 40, x10 + j10);
+    STORE32_LE(out + 44, x11 + j11);
+    STORE32_LE(out + 48, x12 + j12);
+    STORE32_LE(out + 52, x13 + j13);
+    STORE32_LE(out + 56, x14 + j14);
+    STORE32_LE(out + 60, x15 + j15);
+}
+
+int
+crypto_core_salsa20(unsigned char *out, const unsigned char *in,
+                    const unsigned char *k, const unsigned char *c)
+{
+    crypto_core_salsa(out, in, k, c, 20);
+    return 0;
+}
+
+size_t
+crypto_core_salsa20_outputbytes(void)
+{
+    return crypto_core_salsa20_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_salsa20_inputbytes(void)
+{
+    return crypto_core_salsa20_INPUTBYTES;
+}
+
+size_t
+crypto_core_salsa20_keybytes(void)
+{
+    return crypto_core_salsa20_KEYBYTES;
+}
+
+size_t
+crypto_core_salsa20_constbytes(void)
+{
+    return crypto_core_salsa20_CONSTBYTES;
+}
+
+#ifndef MINIMAL
+/* LCOV_EXCL_START */
+int
+crypto_core_salsa2012(unsigned char *out, const unsigned char *in,
+                      const unsigned char *k, const unsigned char *c)
+{
+    crypto_core_salsa(out, in, k, c, 12);
+    return 0;
+}
+
+size_t
+crypto_core_salsa2012_outputbytes(void)
+{
+    return crypto_core_salsa2012_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_salsa2012_inputbytes(void)
+{
+    return crypto_core_salsa2012_INPUTBYTES;
+}
+
+size_t
+crypto_core_salsa2012_keybytes(void)
+{
+    return crypto_core_salsa2012_KEYBYTES;
+}
+
+size_t
+crypto_core_salsa2012_constbytes(void)
+{
+    return crypto_core_salsa2012_CONSTBYTES;
+}
+
+int
+crypto_core_salsa208(unsigned char *out, const unsigned char *in,
+                     const unsigned char *k, const unsigned char *c)
+{
+    crypto_core_salsa(out, in, k, c, 8);
+    return 0;
+}
+
+size_t
+crypto_core_salsa208_outputbytes(void)
+{
+    return crypto_core_salsa208_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_salsa208_inputbytes(void)
+{
+    return crypto_core_salsa208_INPUTBYTES;
+}
+
+size_t
+crypto_core_salsa208_keybytes(void)
+{
+    return crypto_core_salsa208_KEYBYTES;
+}
+
+size_t
+crypto_core_salsa208_constbytes(void)
+{
+    return crypto_core_salsa208_CONSTBYTES;
+}
+/* LCOV_EXCL_END */
+#endif

+ 55 - 0
Sources/Sodium/crypto_generichash/blake2b/generichash_blake2.c

@@ -0,0 +1,55 @@
+#include "crypto_generichash_blake2b.h"
+#include "randombytes.h"
+
+size_t
+crypto_generichash_blake2b_bytes_min(void) {
+    return crypto_generichash_blake2b_BYTES_MIN;
+}
+
+size_t
+crypto_generichash_blake2b_bytes_max(void) {
+    return crypto_generichash_blake2b_BYTES_MAX;
+}
+
+size_t
+crypto_generichash_blake2b_bytes(void) {
+    return crypto_generichash_blake2b_BYTES;
+}
+
+size_t
+crypto_generichash_blake2b_keybytes_min(void) {
+    return crypto_generichash_blake2b_KEYBYTES_MIN;
+}
+
+size_t
+crypto_generichash_blake2b_keybytes_max(void) {
+    return crypto_generichash_blake2b_KEYBYTES_MAX;
+}
+
+size_t
+crypto_generichash_blake2b_keybytes(void) {
+    return crypto_generichash_blake2b_KEYBYTES;
+}
+
+size_t
+crypto_generichash_blake2b_saltbytes(void) {
+    return crypto_generichash_blake2b_SALTBYTES;
+}
+
+size_t
+crypto_generichash_blake2b_personalbytes(void) {
+    return crypto_generichash_blake2b_PERSONALBYTES;
+}
+
+size_t
+crypto_generichash_blake2b_statebytes(void)
+{
+    return (sizeof(crypto_generichash_blake2b_state) + (size_t) 63U)
+        & ~(size_t) 63U;
+}
+
+void
+crypto_generichash_blake2b_keygen(unsigned char k[crypto_generichash_blake2b_KEYBYTES])
+{
+    randombytes_buf(k, crypto_generichash_blake2b_KEYBYTES);
+}

+ 116 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2.h

@@ -0,0 +1,116 @@
+/*
+   BLAKE2 reference source code package - reference C implementations
+
+   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   All code is triple-licensed under the
+   [CC0](http://creativecommons.org/publicdomain/zero/1.0), the
+   [OpenSSL Licence](https://www.openssl.org/source/license.html), or
+   the [Apache Public License 2.0](http://www.apache.org/licenses/LICENSE-2.0),
+   at your choosing.
+ */
+
+#ifndef blake2_H
+#define blake2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "crypto_generichash_blake2b.h"
+#include "export.h"
+
+#define blake2b_init_param crypto_generichash_blake2b__init_param
+#define blake2b_init crypto_generichash_blake2b__init
+#define blake2b_init_salt_personal \
+    crypto_generichash_blake2b__init_salt_personal
+#define blake2b_init_key crypto_generichash_blake2b__init_key
+#define blake2b_init_key_salt_personal \
+    crypto_generichash_blake2b__init_key_salt_personal
+#define blake2b_update crypto_generichash_blake2b__update
+#define blake2b_final crypto_generichash_blake2b__final
+#define blake2b crypto_generichash_blake2b__blake2b
+#define blake2b_salt_personal crypto_generichash_blake2b__blake2b_salt_personal
+#define blake2b_pick_best_implementation \
+    crypto_generichash_blake2b__pick_best_implementation
+
+enum blake2b_constant {
+    BLAKE2B_BLOCKBYTES    = 128,
+    BLAKE2B_OUTBYTES      = 64,
+    BLAKE2B_KEYBYTES      = 64,
+    BLAKE2B_SALTBYTES     = 16,
+    BLAKE2B_PERSONALBYTES = 16
+};
+
+#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
+typedef struct blake2b_param_ {
+    uint8_t digest_length;                   /*  1 */
+    uint8_t key_length;                      /*  2 */
+    uint8_t fanout;                          /*  3 */
+    uint8_t depth;                           /*  4 */
+    uint8_t leaf_length[4];                  /*  8 */
+    uint8_t node_offset[8];                  /* 16 */
+    uint8_t node_depth;                      /* 17 */
+    uint8_t inner_length;                    /* 18 */
+    uint8_t reserved[14];                    /* 32 */
+    uint8_t salt[BLAKE2B_SALTBYTES];         /* 48 */
+    uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+} blake2b_param;
+
+typedef struct blake2b_state {
+    uint64_t h[8];
+    uint64_t t[2];
+    uint64_t f[2];
+    uint8_t  buf[2 * 128];
+    size_t   buflen;
+    uint8_t  last_node;
+} blake2b_state;
+
+#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
+/* Streaming API */
+int blake2b_init(blake2b_state *S, const uint8_t outlen);
+int blake2b_init_salt_personal(blake2b_state *S, const uint8_t outlen,
+                               const void *salt, const void *personal);
+int blake2b_init_key(blake2b_state *S, const uint8_t outlen, const void *key,
+                     const uint8_t keylen);
+int blake2b_init_key_salt_personal(blake2b_state *S, const uint8_t outlen,
+                                   const void *key, const uint8_t keylen,
+                                   const void *salt, const void *personal);
+int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
+int blake2b_update(blake2b_state *S, const uint8_t *in, uint64_t inlen);
+int blake2b_final(blake2b_state *S, uint8_t *out, uint8_t outlen);
+
+/* Simple API */
+int blake2b(uint8_t *out, const void *in, const void *key, const uint8_t outlen,
+            const uint64_t inlen, uint8_t keylen);
+int blake2b_salt_personal(uint8_t *out, const void *in, const void *key,
+                          const uint8_t outlen, const uint64_t inlen,
+                          uint8_t keylen, const void *salt,
+                          const void *personal);
+
+typedef int (*blake2b_compress_fn)(blake2b_state *S,
+                                   const uint8_t  block[BLAKE2B_BLOCKBYTES]);
+int blake2b_pick_best_implementation(void);
+int blake2b_compress_ref(blake2b_state *S,
+                         const uint8_t  block[BLAKE2B_BLOCKBYTES]);
+int blake2b_compress_ssse3(blake2b_state *S,
+                           const uint8_t  block[BLAKE2B_BLOCKBYTES]);
+int blake2b_compress_sse41(blake2b_state *S,
+                           const uint8_t  block[BLAKE2B_BLOCKBYTES]);
+int blake2b_compress_avx2(blake2b_state *S,
+                          const uint8_t  block[BLAKE2B_BLOCKBYTES]);
+
+#endif

+ 49 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c

@@ -0,0 +1,49 @@
+
+#define BLAKE2_USE_SSSE3
+#define BLAKE2_USE_SSE41
+#define BLAKE2_USE_AVX2
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+    defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+#  pragma GCC target("sse2")
+#  pragma GCC target("ssse3")
+#  pragma GCC target("sse4.1")
+#  pragma GCC target("avx2")
+# endif
+
+# include <emmintrin.h>
+# include <immintrin.h>
+# include <smmintrin.h>
+# include <tmmintrin.h>
+
+# include "blake2b-compress-avx2.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+    0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+    0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+    0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+int
+blake2b_compress_avx2(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+    __m256i a = LOADU(&S->h[0]);
+    __m256i b = LOADU(&S->h[4]);
+    BLAKE2B_COMPRESS_V1(a, b, block, S->t[0], S->t[1], S->f[0], S->f[1]);
+    STOREU(&S->h[0], a);
+    STOREU(&S->h[4], b);
+
+    return 0;
+}
+
+#endif

+ 142 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h

@@ -0,0 +1,142 @@
+
+#ifndef blake2b_compress_avx2_H
+#define blake2b_compress_avx2_H
+
+#define LOADU128(p) _mm_loadu_si128((const __m128i *) (p))
+#define STOREU128(p, r) _mm_storeu_si128((__m128i *) (p), r)
+
+#define LOADU(p) _mm256_loadu_si256((const __m256i *) (p))
+#define STOREU(p, r) _mm256_storeu_si256((__m256i *) (p), r)
+
+#if defined(__INTEL_COMPILER) || defined(_MSC_VER) || defined(__GNUC__)
+# define LOAD(p) _mm256_load_si256((const __m256i *) (p))
+# define STORE(p, r) _mm256_store_si256((__m256i *) (p), r)
+#else
+# define LOAD(p) LOADU(p)
+# define STORE(p, r) STOREU(p, r)
+#endif
+
+static inline uint64_t
+LOADU64(const void *p)
+{
+    uint64_t v;
+    memcpy(&v, p, sizeof v);
+    return v;
+}
+
+#define ROTATE16                                                              \
+    _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, \
+                     3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)
+
+#define ROTATE24                                                              \
+    _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, \
+                     4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)
+
+#define ADD(a, b) _mm256_add_epi64(a, b)
+#define SUB(a, b) _mm256_sub_epi64(a, b)
+
+#define XOR(a, b) _mm256_xor_si256(a, b)
+#define AND(a, b) _mm256_and_si256(a, b)
+#define OR(a, b) _mm256_or_si256(a, b)
+
+#define ROT32(x) _mm256_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))
+#define ROT24(x) _mm256_shuffle_epi8((x), ROTATE24)
+#define ROT16(x) _mm256_shuffle_epi8((x), ROTATE16)
+#define ROT63(x) _mm256_or_si256(_mm256_srli_epi64((x), 63), ADD((x), (x)))
+
+#define BLAKE2B_G1_V1(a, b, c, d, m) \
+    do {                             \
+        a = ADD(a, m);               \
+        a = ADD(a, b);               \
+        d = XOR(d, a);               \
+        d = ROT32(d);                \
+        c = ADD(c, d);               \
+        b = XOR(b, c);               \
+        b = ROT24(b);                \
+    } while (0)
+
+#define BLAKE2B_G2_V1(a, b, c, d, m) \
+    do {                             \
+        a = ADD(a, m);               \
+        a = ADD(a, b);               \
+        d = XOR(d, a);               \
+        d = ROT16(d);                \
+        c = ADD(c, d);               \
+        b = XOR(b, c);               \
+        b = ROT63(b);                \
+    } while (0)
+
+#define BLAKE2B_DIAG_V1(a, b, c, d)                               \
+    do {                                                          \
+        a = _mm256_permute4x64_epi64(a, _MM_SHUFFLE(2, 1, 0, 3)); \
+        d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(1, 0, 3, 2)); \
+        c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(0, 3, 2, 1)); \
+    } while(0)
+
+#define BLAKE2B_UNDIAG_V1(a, b, c, d)                             \
+    do {                                                          \
+        a = _mm256_permute4x64_epi64(a, _MM_SHUFFLE(0, 3, 2, 1)); \
+        d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(1, 0, 3, 2)); \
+        c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(2, 1, 0, 3)); \
+    } while(0)
+
+#include "blake2b-load-avx2.h"
+
+#define BLAKE2B_ROUND_V1(a, b, c, d, r, m) \
+    do {                                   \
+        __m256i b0;                        \
+        BLAKE2B_LOAD_MSG_##r##_1(b0);      \
+        BLAKE2B_G1_V1(a, b, c, d, b0);     \
+        BLAKE2B_LOAD_MSG_##r##_2(b0);      \
+        BLAKE2B_G2_V1(a, b, c, d, b0);     \
+        BLAKE2B_DIAG_V1(a, b, c, d);       \
+        BLAKE2B_LOAD_MSG_##r##_3(b0);      \
+        BLAKE2B_G1_V1(a, b, c, d, b0);     \
+        BLAKE2B_LOAD_MSG_##r##_4(b0);      \
+        BLAKE2B_G2_V1(a, b, c, d, b0);     \
+        BLAKE2B_UNDIAG_V1(a, b, c, d);     \
+    } while (0)
+
+#define BLAKE2B_ROUNDS_V1(a, b, c, d, m)       \
+    do {                                       \
+        BLAKE2B_ROUND_V1(a, b, c, d, 0, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 1, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 2, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 3, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 4, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 5, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 6, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 7, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 8, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 9, (m));  \
+        BLAKE2B_ROUND_V1(a, b, c, d, 10, (m)); \
+        BLAKE2B_ROUND_V1(a, b, c, d, 11, (m)); \
+    } while (0)
+
+#define DECLARE_MESSAGE_WORDS(m)                                         \
+    const __m256i m0 = _mm256_broadcastsi128_si256(LOADU128((m) + 0));   \
+    const __m256i m1 = _mm256_broadcastsi128_si256(LOADU128((m) + 16));  \
+    const __m256i m2 = _mm256_broadcastsi128_si256(LOADU128((m) + 32));  \
+    const __m256i m3 = _mm256_broadcastsi128_si256(LOADU128((m) + 48));  \
+    const __m256i m4 = _mm256_broadcastsi128_si256(LOADU128((m) + 64));  \
+    const __m256i m5 = _mm256_broadcastsi128_si256(LOADU128((m) + 80));  \
+    const __m256i m6 = _mm256_broadcastsi128_si256(LOADU128((m) + 96));  \
+    const __m256i m7 = _mm256_broadcastsi128_si256(LOADU128((m) + 112)); \
+    __m256i       t0, t1;
+
+#define BLAKE2B_COMPRESS_V1(a, b, m, t0, t1, f0, f1)                      \
+    do {                                                                  \
+        DECLARE_MESSAGE_WORDS(m)                                          \
+        const __m256i iv0 = a;                                            \
+        const __m256i iv1 = b;                                            \
+        __m256i       c   = LOAD(&blake2b_IV[0]);                         \
+        __m256i       d =                                                 \
+            XOR(LOAD(&blake2b_IV[4]), _mm256_set_epi64x(f1, f0, t1, t0)); \
+        BLAKE2B_ROUNDS_V1(a, b, c, d, m);                                 \
+        a = XOR(a, c);                                                    \
+        b = XOR(b, d);                                                    \
+        a = XOR(a, iv0);                                                  \
+        b = XOR(b, iv1);                                                  \
+    } while (0)
+
+#endif

+ 93 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-ref.c

@@ -0,0 +1,93 @@
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+    0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+    0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+    0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const uint8_t blake2b_sigma[12][16] = {
+    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+    { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
+    { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
+    { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
+    { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
+    { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
+    { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
+    { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
+    { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
+    { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
+    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+    { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+};
+
+int
+blake2b_compress_ref(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+    uint64_t m[16];
+    uint64_t v[16];
+    int      i;
+
+    for (i = 0; i < 16; ++i) {
+        m[i] = LOAD64_LE(block + i * sizeof m[i]);
+    }
+    for (i = 0; i < 8; ++i) {
+        v[i] = S->h[i];
+    }
+    v[8]  = blake2b_IV[0];
+    v[9]  = blake2b_IV[1];
+    v[10] = blake2b_IV[2];
+    v[11] = blake2b_IV[3];
+    v[12] = S->t[0] ^ blake2b_IV[4];
+    v[13] = S->t[1] ^ blake2b_IV[5];
+    v[14] = S->f[0] ^ blake2b_IV[6];
+    v[15] = S->f[1] ^ blake2b_IV[7];
+#define G(r, i, a, b, c, d)                      \
+    do {                                         \
+        a += b + m[blake2b_sigma[r][2 * i + 0]]; \
+        d = ROTR64(d ^ a, 32);                   \
+        c += d;                                  \
+        b = ROTR64(b ^ c, 24);                   \
+        a += b + m[blake2b_sigma[r][2 * i + 1]]; \
+        d = ROTR64(d ^ a, 16);                   \
+        c += d;                                  \
+        b = ROTR64(b ^ c, 63);                   \
+    } while (0)
+#define ROUND(r)                           \
+    do {                                   \
+        G(r, 0, v[0], v[4], v[8], v[12]);  \
+        G(r, 1, v[1], v[5], v[9], v[13]);  \
+        G(r, 2, v[2], v[6], v[10], v[14]); \
+        G(r, 3, v[3], v[7], v[11], v[15]); \
+        G(r, 4, v[0], v[5], v[10], v[15]); \
+        G(r, 5, v[1], v[6], v[11], v[12]); \
+        G(r, 6, v[2], v[7], v[8], v[13]);  \
+        G(r, 7, v[3], v[4], v[9], v[14]);  \
+    } while (0)
+    ROUND(0);
+    ROUND(1);
+    ROUND(2);
+    ROUND(3);
+    ROUND(4);
+    ROUND(5);
+    ROUND(6);
+    ROUND(7);
+    ROUND(8);
+    ROUND(9);
+    ROUND(10);
+    ROUND(11);
+
+    for (i = 0; i < 8; ++i) {
+        S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+    }
+
+#undef G
+#undef ROUND
+    return 0;
+}

+ 87 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c

@@ -0,0 +1,87 @@
+
+#define BLAKE2_USE_SSSE3
+#define BLAKE2_USE_SSE41
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+    defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+#  pragma GCC target("sse2")
+#  pragma GCC target("ssse3")
+#  pragma GCC target("sse4.1")
+# endif
+
+# include <emmintrin.h>
+# include <smmintrin.h>
+# include <tmmintrin.h>
+
+# include "blake2b-compress-sse41.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+    0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+    0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+    0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+int
+blake2b_compress_sse41(blake2b_state *S,
+                       const uint8_t  block[BLAKE2B_BLOCKBYTES])
+{
+    __m128i       row1l, row1h;
+    __m128i       row2l, row2h;
+    __m128i       row3l, row3h;
+    __m128i       row4l, row4h;
+    __m128i       b0, b1;
+    __m128i       t0, t1;
+    const __m128i r16 =
+        _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9);
+    const __m128i r24 =
+        _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10);
+    const __m128i m0 = LOADU(block + 00);
+    const __m128i m1 = LOADU(block + 16);
+    const __m128i m2 = LOADU(block + 32);
+    const __m128i m3 = LOADU(block + 48);
+    const __m128i m4 = LOADU(block + 64);
+    const __m128i m5 = LOADU(block + 80);
+    const __m128i m6 = LOADU(block + 96);
+    const __m128i m7 = LOADU(block + 112);
+    row1l            = LOADU(&S->h[0]);
+    row1h            = LOADU(&S->h[2]);
+    row2l            = LOADU(&S->h[4]);
+    row2h            = LOADU(&S->h[6]);
+    row3l            = LOADU(&blake2b_IV[0]);
+    row3h            = LOADU(&blake2b_IV[2]);
+    row4l            = _mm_xor_si128(LOADU(&blake2b_IV[4]), LOADU(&S->t[0]));
+    row4h            = _mm_xor_si128(LOADU(&blake2b_IV[6]), LOADU(&S->f[0]));
+    ROUND(0);
+    ROUND(1);
+    ROUND(2);
+    ROUND(3);
+    ROUND(4);
+    ROUND(5);
+    ROUND(6);
+    ROUND(7);
+    ROUND(8);
+    ROUND(9);
+    ROUND(10);
+    ROUND(11);
+    row1l = _mm_xor_si128(row3l, row1l);
+    row1h = _mm_xor_si128(row3h, row1h);
+    STOREU(&S->h[0], _mm_xor_si128(LOADU(&S->h[0]), row1l));
+    STOREU(&S->h[2], _mm_xor_si128(LOADU(&S->h[2]), row1h));
+    row2l = _mm_xor_si128(row4l, row2l);
+    row2h = _mm_xor_si128(row4h, row2h);
+    STOREU(&S->h[4], _mm_xor_si128(LOADU(&S->h[4]), row2l));
+    STOREU(&S->h[6], _mm_xor_si128(LOADU(&S->h[6]), row2h));
+    return 0;
+}
+
+#endif

+ 103 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h

@@ -0,0 +1,103 @@
+
+#ifndef blake2b_compress_sse41_H
+#define blake2b_compress_sse41_H
+
+#define LOADU(p) _mm_loadu_si128((const __m128i *) (const void *) (p))
+#define STOREU(p, r) _mm_storeu_si128((__m128i *) (void *) (p), r)
+
+#define _mm_roti_epi64(x, c)                                         \
+    (-(c) == 32)                                                     \
+        ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))            \
+        : (-(c) == 24)                                               \
+              ? _mm_shuffle_epi8((x), r24)                           \
+              : (-(c) == 16)                                         \
+                    ? _mm_shuffle_epi8((x), r16)                     \
+                    : (-(c) == 63)                                   \
+                          ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+                                          _mm_add_epi64((x), (x)))   \
+                          : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+                                          _mm_slli_epi64((x), 64 - (-(c))))
+
+#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+    row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l);                \
+    row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h);                \
+                                                                           \
+    row4l = _mm_xor_si128(row4l, row1l);                                   \
+    row4h = _mm_xor_si128(row4h, row1h);                                   \
+                                                                           \
+    row4l = _mm_roti_epi64(row4l, -32);                                    \
+    row4h = _mm_roti_epi64(row4h, -32);                                    \
+                                                                           \
+    row3l = _mm_add_epi64(row3l, row4l);                                   \
+    row3h = _mm_add_epi64(row3h, row4h);                                   \
+                                                                           \
+    row2l = _mm_xor_si128(row2l, row3l);                                   \
+    row2h = _mm_xor_si128(row2h, row3h);                                   \
+                                                                           \
+    row2l = _mm_roti_epi64(row2l, -24);                                    \
+    row2h = _mm_roti_epi64(row2h, -24);
+
+#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+    row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l);                \
+    row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h);                \
+                                                                           \
+    row4l = _mm_xor_si128(row4l, row1l);                                   \
+    row4h = _mm_xor_si128(row4h, row1h);                                   \
+                                                                           \
+    row4l = _mm_roti_epi64(row4l, -16);                                    \
+    row4h = _mm_roti_epi64(row4h, -16);                                    \
+                                                                           \
+    row3l = _mm_add_epi64(row3l, row4l);                                   \
+    row3h = _mm_add_epi64(row3h, row4h);                                   \
+                                                                           \
+    row2l = _mm_xor_si128(row2l, row3l);                                   \
+    row2h = _mm_xor_si128(row2h, row3h);                                   \
+                                                                           \
+    row2l = _mm_roti_epi64(row2l, -63);                                    \
+    row2h = _mm_roti_epi64(row2h, -63);
+
+#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+    t0    = _mm_alignr_epi8(row2h, row2l, 8);                               \
+    t1    = _mm_alignr_epi8(row2l, row2h, 8);                               \
+    row2l = t0;                                                             \
+    row2h = t1;                                                             \
+                                                                            \
+    t0    = row3l;                                                          \
+    row3l = row3h;                                                          \
+    row3h = t0;                                                             \
+                                                                            \
+    t0    = _mm_alignr_epi8(row4h, row4l, 8);                               \
+    t1    = _mm_alignr_epi8(row4l, row4h, 8);                               \
+    row4l = t1;                                                             \
+    row4h = t0;
+
+#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+    t0    = _mm_alignr_epi8(row2l, row2h, 8);                                 \
+    t1    = _mm_alignr_epi8(row2h, row2l, 8);                                 \
+    row2l = t0;                                                               \
+    row2h = t1;                                                               \
+                                                                              \
+    t0    = row3l;                                                            \
+    row3l = row3h;                                                            \
+    row3h = t0;                                                               \
+                                                                              \
+    t0    = _mm_alignr_epi8(row4l, row4h, 8);                                 \
+    t1    = _mm_alignr_epi8(row4h, row4l, 8);                                 \
+    row4l = t1;                                                               \
+    row4h = t0;
+
+#include "blake2b-load-sse41.h"
+
+#define ROUND(r)                                                         \
+    LOAD_MSG_##r##_1(b0, b1);                                            \
+    G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    LOAD_MSG_##r##_2(b0, b1);                                            \
+    G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
+    LOAD_MSG_##r##_3(b0, b1);                                            \
+    G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    LOAD_MSG_##r##_4(b0, b1);                                            \
+    G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);
+
+#endif

+ 90 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c

@@ -0,0 +1,90 @@
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+
+# ifdef __GNUC__
+#  pragma GCC target("sse2")
+#  pragma GCC target("ssse3")
+# endif
+
+# include <emmintrin.h>
+# include <tmmintrin.h>
+
+# include "blake2b-compress-ssse3.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+    0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+    0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+    0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+int
+blake2b_compress_ssse3(blake2b_state *S,
+                       const uint8_t  block[BLAKE2B_BLOCKBYTES])
+{
+    __m128i       row1l, row1h;
+    __m128i       row2l, row2h;
+    __m128i       row3l, row3h;
+    __m128i       row4l, row4h;
+    __m128i       b0, b1;
+    __m128i       t0, t1;
+    const __m128i r16 =
+        _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9);
+    const __m128i r24 =
+        _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10);
+    const uint64_t m0  = ((const uint64_t *) block)[0];
+    const uint64_t m1  = ((const uint64_t *) block)[1];
+    const uint64_t m2  = ((const uint64_t *) block)[2];
+    const uint64_t m3  = ((const uint64_t *) block)[3];
+    const uint64_t m4  = ((const uint64_t *) block)[4];
+    const uint64_t m5  = ((const uint64_t *) block)[5];
+    const uint64_t m6  = ((const uint64_t *) block)[6];
+    const uint64_t m7  = ((const uint64_t *) block)[7];
+    const uint64_t m8  = ((const uint64_t *) block)[8];
+    const uint64_t m9  = ((const uint64_t *) block)[9];
+    const uint64_t m10 = ((const uint64_t *) block)[10];
+    const uint64_t m11 = ((const uint64_t *) block)[11];
+    const uint64_t m12 = ((const uint64_t *) block)[12];
+    const uint64_t m13 = ((const uint64_t *) block)[13];
+    const uint64_t m14 = ((const uint64_t *) block)[14];
+    const uint64_t m15 = ((const uint64_t *) block)[15];
+
+    row1l = LOADU(&S->h[0]);
+    row1h = LOADU(&S->h[2]);
+    row2l = LOADU(&S->h[4]);
+    row2h = LOADU(&S->h[6]);
+    row3l = LOADU(&blake2b_IV[0]);
+    row3h = LOADU(&blake2b_IV[2]);
+    row4l = _mm_xor_si128(LOADU(&blake2b_IV[4]), LOADU(&S->t[0]));
+    row4h = _mm_xor_si128(LOADU(&blake2b_IV[6]), LOADU(&S->f[0]));
+    ROUND(0);
+    ROUND(1);
+    ROUND(2);
+    ROUND(3);
+    ROUND(4);
+    ROUND(5);
+    ROUND(6);
+    ROUND(7);
+    ROUND(8);
+    ROUND(9);
+    ROUND(10);
+    ROUND(11);
+    row1l = _mm_xor_si128(row3l, row1l);
+    row1h = _mm_xor_si128(row3h, row1h);
+    STOREU(&S->h[0], _mm_xor_si128(LOADU(&S->h[0]), row1l));
+    STOREU(&S->h[2], _mm_xor_si128(LOADU(&S->h[2]), row1h));
+    row2l = _mm_xor_si128(row4l, row2l);
+    row2h = _mm_xor_si128(row4h, row2h);
+    STOREU(&S->h[4], _mm_xor_si128(LOADU(&S->h[4]), row2l));
+    STOREU(&S->h[6], _mm_xor_si128(LOADU(&S->h[6]), row2h));
+    return 0;
+}
+
+#endif

+ 103 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h

@@ -0,0 +1,103 @@
+
+#ifndef blake2b_compress_ssse3_H
+#define blake2b_compress_ssse3_H
+
+#define LOADU(p) _mm_loadu_si128((const __m128i *) (const void *) (p))
+#define STOREU(p, r) _mm_storeu_si128((__m128i *) (void *) (p), r)
+
+#define _mm_roti_epi64(x, c)                                         \
+    (-(c) == 32)                                                     \
+        ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))            \
+        : (-(c) == 24)                                               \
+              ? _mm_shuffle_epi8((x), r24)                           \
+              : (-(c) == 16)                                         \
+                    ? _mm_shuffle_epi8((x), r16)                     \
+                    : (-(c) == 63)                                   \
+                          ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+                                          _mm_add_epi64((x), (x)))   \
+                          : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+                                          _mm_slli_epi64((x), 64 - (-(c))))
+
+#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+    row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l);                \
+    row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h);                \
+                                                                           \
+    row4l = _mm_xor_si128(row4l, row1l);                                   \
+    row4h = _mm_xor_si128(row4h, row1h);                                   \
+                                                                           \
+    row4l = _mm_roti_epi64(row4l, -32);                                    \
+    row4h = _mm_roti_epi64(row4h, -32);                                    \
+                                                                           \
+    row3l = _mm_add_epi64(row3l, row4l);                                   \
+    row3h = _mm_add_epi64(row3h, row4h);                                   \
+                                                                           \
+    row2l = _mm_xor_si128(row2l, row3l);                                   \
+    row2h = _mm_xor_si128(row2h, row3h);                                   \
+                                                                           \
+    row2l = _mm_roti_epi64(row2l, -24);                                    \
+    row2h = _mm_roti_epi64(row2h, -24);
+
+#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+    row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l);                \
+    row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h);                \
+                                                                           \
+    row4l = _mm_xor_si128(row4l, row1l);                                   \
+    row4h = _mm_xor_si128(row4h, row1h);                                   \
+                                                                           \
+    row4l = _mm_roti_epi64(row4l, -16);                                    \
+    row4h = _mm_roti_epi64(row4h, -16);                                    \
+                                                                           \
+    row3l = _mm_add_epi64(row3l, row4l);                                   \
+    row3h = _mm_add_epi64(row3h, row4h);                                   \
+                                                                           \
+    row2l = _mm_xor_si128(row2l, row3l);                                   \
+    row2h = _mm_xor_si128(row2h, row3h);                                   \
+                                                                           \
+    row2l = _mm_roti_epi64(row2l, -63);                                    \
+    row2h = _mm_roti_epi64(row2h, -63);
+
+#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+    t0    = _mm_alignr_epi8(row2h, row2l, 8);                               \
+    t1    = _mm_alignr_epi8(row2l, row2h, 8);                               \
+    row2l = t0;                                                             \
+    row2h = t1;                                                             \
+                                                                            \
+    t0    = row3l;                                                          \
+    row3l = row3h;                                                          \
+    row3h = t0;                                                             \
+                                                                            \
+    t0    = _mm_alignr_epi8(row4h, row4l, 8);                               \
+    t1    = _mm_alignr_epi8(row4l, row4h, 8);                               \
+    row4l = t1;                                                             \
+    row4h = t0;
+
+#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+    t0    = _mm_alignr_epi8(row2l, row2h, 8);                                 \
+    t1    = _mm_alignr_epi8(row2h, row2l, 8);                                 \
+    row2l = t0;                                                               \
+    row2h = t1;                                                               \
+                                                                              \
+    t0    = row3l;                                                            \
+    row3l = row3h;                                                            \
+    row3h = t0;                                                               \
+                                                                              \
+    t0    = _mm_alignr_epi8(row4l, row4h, 8);                                 \
+    t1    = _mm_alignr_epi8(row4h, row4l, 8);                                 \
+    row4l = t1;                                                               \
+    row4h = t0;
+
+#include "blake2b-load-sse2.h"
+
+#define ROUND(r)                                                         \
+    LOAD_MSG_##r##_1(b0, b1);                                            \
+    G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    LOAD_MSG_##r##_2(b0, b1);                                            \
+    G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
+    LOAD_MSG_##r##_3(b0, b1);                                            \
+    G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    LOAD_MSG_##r##_4(b0, b1);                                            \
+    G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1);  \
+    UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);
+
+#endif

+ 340 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-load-avx2.h

@@ -0,0 +1,340 @@
+#ifndef blake2b_load_avx2_H
+#define blake2b_load_avx2_H
+
+#define BLAKE2B_LOAD_MSG_0_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m0, m1);    \
+        t1 = _mm256_unpacklo_epi64(m2, m3);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_0_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m0, m1);    \
+        t1 = _mm256_unpackhi_epi64(m2, m3);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_0_3(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m7, m4);    \
+        t1 = _mm256_unpacklo_epi64(m5, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_0_4(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m7, m4);    \
+        t1 = _mm256_unpackhi_epi64(m5, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m7, m2);    \
+        t1 = _mm256_unpackhi_epi64(m4, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m5, m4);    \
+        t1 = _mm256_alignr_epi8(m3, m7, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_3(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m2, m0);    \
+        t1 = _mm256_blend_epi32(m5, m0, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_4(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m6, m1, 8);    \
+        t1 = _mm256_blend_epi32(m3, m1, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_1(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m6, m5, 8);    \
+        t1 = _mm256_unpackhi_epi64(m2, m7);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m4, m0);    \
+        t1 = _mm256_blend_epi32(m6, m1, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_3(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m5, m4, 8);    \
+        t1 = _mm256_unpackhi_epi64(m1, m3);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_4(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m2, m7);    \
+        t1 = _mm256_blend_epi32(m0, m3, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m3, m1);    \
+        t1 = _mm256_unpackhi_epi64(m6, m5);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m4, m0);    \
+        t1 = _mm256_unpacklo_epi64(m6, m7);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_3(b0)                                \
+    do {                                                        \
+        t0 = _mm256_alignr_epi8(m1, m7, 8);                     \
+        t1 = _mm256_shuffle_epi32(m2, _MM_SHUFFLE(1, 0, 3, 2)); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0);                  \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_4(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m4, m3);    \
+        t1 = _mm256_unpacklo_epi64(m5, m0);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m4, m2);    \
+        t1 = _mm256_unpacklo_epi64(m1, m5);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_2(b0)               \
+    do {                                       \
+        t0 = _mm256_blend_epi32(m3, m0, 0x33); \
+        t1 = _mm256_blend_epi32(m7, m2, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_3(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m7, m1, 8);    \
+        t1 = _mm256_alignr_epi8(m3, m5, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_4(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m6, m0);    \
+        t1 = _mm256_unpacklo_epi64(m6, m4);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m1, m3);    \
+        t1 = _mm256_unpacklo_epi64(m0, m4);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m6, m5);    \
+        t1 = _mm256_unpackhi_epi64(m5, m1);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_3(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m2, m0, 8);    \
+        t1 = _mm256_unpackhi_epi64(m3, m7);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_4(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m4, m6);    \
+        t1 = _mm256_alignr_epi8(m7, m2, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_1(b0)               \
+    do {                                       \
+        t0 = _mm256_blend_epi32(m0, m6, 0x33); \
+        t1 = _mm256_unpacklo_epi64(m7, m2);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m2, m7);    \
+        t1 = _mm256_alignr_epi8(m5, m6, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_3(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m4, m0);    \
+        t1 = _mm256_blend_epi32(m4, m3, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_4(b0)                                \
+    do {                                                        \
+        t0 = _mm256_unpackhi_epi64(m5, m3);                     \
+        t1 = _mm256_shuffle_epi32(m1, _MM_SHUFFLE(1, 0, 3, 2)); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0);                  \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m6, m3);    \
+        t1 = _mm256_blend_epi32(m1, m6, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_2(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m7, m5, 8);    \
+        t1 = _mm256_unpackhi_epi64(m0, m4);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_3(b0)               \
+    do {                                       \
+        t0 = _mm256_blend_epi32(m2, m1, 0x33); \
+        t1 = _mm256_alignr_epi8(m4, m7, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_4(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m5, m0);    \
+        t1 = _mm256_unpacklo_epi64(m2, m3);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m3, m7);    \
+        t1 = _mm256_alignr_epi8(m0, m5, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m7, m4);    \
+        t1 = _mm256_alignr_epi8(m4, m1, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_3(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m5, m6);    \
+        t1 = _mm256_unpackhi_epi64(m6, m0);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_4(b0)               \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m1, m2, 8);    \
+        t1 = _mm256_alignr_epi8(m2, m3, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_1(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m5, m4);    \
+        t1 = _mm256_unpackhi_epi64(m3, m0);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_2(b0)               \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m1, m2);    \
+        t1 = _mm256_blend_epi32(m2, m3, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_3(b0)               \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m6, m7);    \
+        t1 = _mm256_unpackhi_epi64(m4, m1);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_4(b0)               \
+    do {                                       \
+        t0 = _mm256_blend_epi32(m5, m0, 0x33); \
+        t1 = _mm256_unpacklo_epi64(m7, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_1(b0)              \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m0, m1);    \
+        t1 = _mm256_unpacklo_epi64(m2, m3);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_2(b0)              \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m0, m1);    \
+        t1 = _mm256_unpackhi_epi64(m2, m3);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_3(b0)              \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m7, m4);    \
+        t1 = _mm256_unpacklo_epi64(m5, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_4(b0)              \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m7, m4);    \
+        t1 = _mm256_unpackhi_epi64(m5, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_1(b0)              \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m7, m2);    \
+        t1 = _mm256_unpackhi_epi64(m4, m6);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_2(b0)              \
+    do {                                       \
+        t0 = _mm256_unpacklo_epi64(m5, m4);    \
+        t1 = _mm256_alignr_epi8(m3, m7, 8);    \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_3(b0)              \
+    do {                                       \
+        t0 = _mm256_unpackhi_epi64(m2, m0);    \
+        t1 = _mm256_blend_epi32(m5, m0, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_4(b0)              \
+    do {                                       \
+        t0 = _mm256_alignr_epi8(m6, m1, 8);    \
+        t1 = _mm256_blend_epi32(m3, m1, 0x33); \
+        b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+    } while (0)
+
+#endif

+ 164 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-load-sse2.h

@@ -0,0 +1,164 @@
+/*
+   BLAKE2 reference source code package - optimized C implementations
+
+   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   You should have received a copy of the CC0 Public Domain Dedication along
+   with
+   this software. If not, see
+   <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+
+#ifndef blake2b_load_sse2_H
+#define blake2b_load_sse2_H
+
+#define LOAD_MSG_0_1(b0, b1)     \
+    b0 = _mm_set_epi64x(m2, m0); \
+    b1 = _mm_set_epi64x(m6, m4)
+#define LOAD_MSG_0_2(b0, b1)     \
+    b0 = _mm_set_epi64x(m3, m1); \
+    b1 = _mm_set_epi64x(m7, m5)
+#define LOAD_MSG_0_3(b0, b1)      \
+    b0 = _mm_set_epi64x(m10, m8); \
+    b1 = _mm_set_epi64x(m14, m12)
+#define LOAD_MSG_0_4(b0, b1)      \
+    b0 = _mm_set_epi64x(m11, m9); \
+    b1 = _mm_set_epi64x(m15, m13)
+#define LOAD_MSG_1_1(b0, b1)      \
+    b0 = _mm_set_epi64x(m4, m14); \
+    b1 = _mm_set_epi64x(m13, m9)
+#define LOAD_MSG_1_2(b0, b1)      \
+    b0 = _mm_set_epi64x(m8, m10); \
+    b1 = _mm_set_epi64x(m6, m15)
+#define LOAD_MSG_1_3(b0, b1)     \
+    b0 = _mm_set_epi64x(m0, m1); \
+    b1 = _mm_set_epi64x(m5, m11)
+#define LOAD_MSG_1_4(b0, b1)      \
+    b0 = _mm_set_epi64x(m2, m12); \
+    b1 = _mm_set_epi64x(m3, m7)
+#define LOAD_MSG_2_1(b0, b1)       \
+    b0 = _mm_set_epi64x(m12, m11); \
+    b1 = _mm_set_epi64x(m15, m5)
+#define LOAD_MSG_2_2(b0, b1)     \
+    b0 = _mm_set_epi64x(m0, m8); \
+    b1 = _mm_set_epi64x(m13, m2)
+#define LOAD_MSG_2_3(b0, b1)      \
+    b0 = _mm_set_epi64x(m3, m10); \
+    b1 = _mm_set_epi64x(m9, m7)
+#define LOAD_MSG_2_4(b0, b1)      \
+    b0 = _mm_set_epi64x(m6, m14); \
+    b1 = _mm_set_epi64x(m4, m1)
+#define LOAD_MSG_3_1(b0, b1)     \
+    b0 = _mm_set_epi64x(m3, m7); \
+    b1 = _mm_set_epi64x(m11, m13)
+#define LOAD_MSG_3_2(b0, b1)     \
+    b0 = _mm_set_epi64x(m1, m9); \
+    b1 = _mm_set_epi64x(m14, m12)
+#define LOAD_MSG_3_3(b0, b1)     \
+    b0 = _mm_set_epi64x(m5, m2); \
+    b1 = _mm_set_epi64x(m15, m4)
+#define LOAD_MSG_3_4(b0, b1)      \
+    b0 = _mm_set_epi64x(m10, m6); \
+    b1 = _mm_set_epi64x(m8, m0)
+#define LOAD_MSG_4_1(b0, b1)     \
+    b0 = _mm_set_epi64x(m5, m9); \
+    b1 = _mm_set_epi64x(m10, m2)
+#define LOAD_MSG_4_2(b0, b1)     \
+    b0 = _mm_set_epi64x(m7, m0); \
+    b1 = _mm_set_epi64x(m15, m4)
+#define LOAD_MSG_4_3(b0, b1)       \
+    b0 = _mm_set_epi64x(m11, m14); \
+    b1 = _mm_set_epi64x(m3, m6)
+#define LOAD_MSG_4_4(b0, b1)      \
+    b0 = _mm_set_epi64x(m12, m1); \
+    b1 = _mm_set_epi64x(m13, m8)
+#define LOAD_MSG_5_1(b0, b1)     \
+    b0 = _mm_set_epi64x(m6, m2); \
+    b1 = _mm_set_epi64x(m8, m0)
+#define LOAD_MSG_5_2(b0, b1)       \
+    b0 = _mm_set_epi64x(m10, m12); \
+    b1 = _mm_set_epi64x(m3, m11)
+#define LOAD_MSG_5_3(b0, b1)     \
+    b0 = _mm_set_epi64x(m7, m4); \
+    b1 = _mm_set_epi64x(m1, m15)
+#define LOAD_MSG_5_4(b0, b1)      \
+    b0 = _mm_set_epi64x(m5, m13); \
+    b1 = _mm_set_epi64x(m9, m14)
+#define LOAD_MSG_6_1(b0, b1)      \
+    b0 = _mm_set_epi64x(m1, m12); \
+    b1 = _mm_set_epi64x(m4, m14)
+#define LOAD_MSG_6_2(b0, b1)      \
+    b0 = _mm_set_epi64x(m15, m5); \
+    b1 = _mm_set_epi64x(m10, m13)
+#define LOAD_MSG_6_3(b0, b1)     \
+    b0 = _mm_set_epi64x(m6, m0); \
+    b1 = _mm_set_epi64x(m8, m9)
+#define LOAD_MSG_6_4(b0, b1)     \
+    b0 = _mm_set_epi64x(m3, m7); \
+    b1 = _mm_set_epi64x(m11, m2)
+#define LOAD_MSG_7_1(b0, b1)      \
+    b0 = _mm_set_epi64x(m7, m13); \
+    b1 = _mm_set_epi64x(m3, m12)
+#define LOAD_MSG_7_2(b0, b1)       \
+    b0 = _mm_set_epi64x(m14, m11); \
+    b1 = _mm_set_epi64x(m9, m1)
+#define LOAD_MSG_7_3(b0, b1)      \
+    b0 = _mm_set_epi64x(m15, m5); \
+    b1 = _mm_set_epi64x(m2, m8)
+#define LOAD_MSG_7_4(b0, b1)     \
+    b0 = _mm_set_epi64x(m4, m0); \
+    b1 = _mm_set_epi64x(m10, m6)
+#define LOAD_MSG_8_1(b0, b1)      \
+    b0 = _mm_set_epi64x(m14, m6); \
+    b1 = _mm_set_epi64x(m0, m11)
+#define LOAD_MSG_8_2(b0, b1)      \
+    b0 = _mm_set_epi64x(m9, m15); \
+    b1 = _mm_set_epi64x(m8, m3)
+#define LOAD_MSG_8_3(b0, b1)       \
+    b0 = _mm_set_epi64x(m13, m12); \
+    b1 = _mm_set_epi64x(m10, m1)
+#define LOAD_MSG_8_4(b0, b1)     \
+    b0 = _mm_set_epi64x(m7, m2); \
+    b1 = _mm_set_epi64x(m5, m4)
+#define LOAD_MSG_9_1(b0, b1)      \
+    b0 = _mm_set_epi64x(m8, m10); \
+    b1 = _mm_set_epi64x(m1, m7)
+#define LOAD_MSG_9_2(b0, b1)     \
+    b0 = _mm_set_epi64x(m4, m2); \
+    b1 = _mm_set_epi64x(m5, m6)
+#define LOAD_MSG_9_3(b0, b1)      \
+    b0 = _mm_set_epi64x(m9, m15); \
+    b1 = _mm_set_epi64x(m13, m3)
+#define LOAD_MSG_9_4(b0, b1)       \
+    b0 = _mm_set_epi64x(m14, m11); \
+    b1 = _mm_set_epi64x(m0, m12)
+#define LOAD_MSG_10_1(b0, b1)    \
+    b0 = _mm_set_epi64x(m2, m0); \
+    b1 = _mm_set_epi64x(m6, m4)
+#define LOAD_MSG_10_2(b0, b1)    \
+    b0 = _mm_set_epi64x(m3, m1); \
+    b1 = _mm_set_epi64x(m7, m5)
+#define LOAD_MSG_10_3(b0, b1)     \
+    b0 = _mm_set_epi64x(m10, m8); \
+    b1 = _mm_set_epi64x(m14, m12)
+#define LOAD_MSG_10_4(b0, b1)     \
+    b0 = _mm_set_epi64x(m11, m9); \
+    b1 = _mm_set_epi64x(m15, m13)
+#define LOAD_MSG_11_1(b0, b1)     \
+    b0 = _mm_set_epi64x(m4, m14); \
+    b1 = _mm_set_epi64x(m13, m9)
+#define LOAD_MSG_11_2(b0, b1)     \
+    b0 = _mm_set_epi64x(m8, m10); \
+    b1 = _mm_set_epi64x(m6, m15)
+#define LOAD_MSG_11_3(b0, b1)    \
+    b0 = _mm_set_epi64x(m0, m1); \
+    b1 = _mm_set_epi64x(m5, m11)
+#define LOAD_MSG_11_4(b0, b1)     \
+    b0 = _mm_set_epi64x(m2, m12); \
+    b1 = _mm_set_epi64x(m3, m7)
+
+#endif

+ 307 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-load-sse41.h

@@ -0,0 +1,307 @@
+/*
+   BLAKE2 reference source code package - optimized C implementations
+
+   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   You should have received a copy of the CC0 Public Domain Dedication along
+   with
+   this software. If not, see
+   <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+
+#ifndef blake2b_load_sse41_H
+#define blake2b_load_sse41_H
+
+#define LOAD_MSG_0_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m0, m1); \
+        b1 = _mm_unpacklo_epi64(m2, m3); \
+    } while (0)
+
+#define LOAD_MSG_0_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m0, m1); \
+        b1 = _mm_unpackhi_epi64(m2, m3); \
+    } while (0)
+
+#define LOAD_MSG_0_3(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m4, m5); \
+        b1 = _mm_unpacklo_epi64(m6, m7); \
+    } while (0)
+
+#define LOAD_MSG_0_4(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m4, m5); \
+        b1 = _mm_unpackhi_epi64(m6, m7); \
+    } while (0)
+
+#define LOAD_MSG_1_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m7, m2); \
+        b1 = _mm_unpackhi_epi64(m4, m6); \
+    } while (0)
+
+#define LOAD_MSG_1_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m5, m4); \
+        b1 = _mm_alignr_epi8(m3, m7, 8); \
+    } while (0)
+
+#define LOAD_MSG_1_3(b0, b1)                                 \
+    do {                                                     \
+        b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2)); \
+        b1 = _mm_unpackhi_epi64(m5, m2);                     \
+    } while (0)
+
+#define LOAD_MSG_1_4(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m6, m1); \
+        b1 = _mm_unpackhi_epi64(m3, m1); \
+    } while (0)
+
+#define LOAD_MSG_2_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_alignr_epi8(m6, m5, 8); \
+        b1 = _mm_unpackhi_epi64(m2, m7); \
+    } while (0)
+
+#define LOAD_MSG_2_2(b0, b1)                \
+    do {                                    \
+        b0 = _mm_unpacklo_epi64(m4, m0);    \
+        b1 = _mm_blend_epi16(m1, m6, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_2_3(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m5, m1, 0xF0); \
+        b1 = _mm_unpackhi_epi64(m3, m4);    \
+    } while (0)
+
+#define LOAD_MSG_2_4(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m7, m3); \
+        b1 = _mm_alignr_epi8(m2, m0, 8); \
+    } while (0)
+
+#define LOAD_MSG_3_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m3, m1); \
+        b1 = _mm_unpackhi_epi64(m6, m5); \
+    } while (0)
+
+#define LOAD_MSG_3_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m4, m0); \
+        b1 = _mm_unpacklo_epi64(m6, m7); \
+    } while (0)
+
+#define LOAD_MSG_3_3(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m1, m2, 0xF0); \
+        b1 = _mm_blend_epi16(m2, m7, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_3_4(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m3, m5); \
+        b1 = _mm_unpacklo_epi64(m0, m4); \
+    } while (0)
+
+#define LOAD_MSG_4_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m4, m2); \
+        b1 = _mm_unpacklo_epi64(m1, m5); \
+    } while (0)
+
+#define LOAD_MSG_4_2(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m0, m3, 0xF0); \
+        b1 = _mm_blend_epi16(m2, m7, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_4_3(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m7, m5, 0xF0); \
+        b1 = _mm_blend_epi16(m3, m1, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_4_4(b0, b1)                \
+    do {                                    \
+        b0 = _mm_alignr_epi8(m6, m0, 8);    \
+        b1 = _mm_blend_epi16(m4, m6, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_5_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m1, m3); \
+        b1 = _mm_unpacklo_epi64(m0, m4); \
+    } while (0)
+
+#define LOAD_MSG_5_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m6, m5); \
+        b1 = _mm_unpackhi_epi64(m5, m1); \
+    } while (0)
+
+#define LOAD_MSG_5_3(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m2, m3, 0xF0); \
+        b1 = _mm_unpackhi_epi64(m7, m0);    \
+    } while (0)
+
+#define LOAD_MSG_5_4(b0, b1)                \
+    do {                                    \
+        b0 = _mm_unpackhi_epi64(m6, m2);    \
+        b1 = _mm_blend_epi16(m7, m4, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_6_1(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m6, m0, 0xF0); \
+        b1 = _mm_unpacklo_epi64(m7, m2);    \
+    } while (0)
+
+#define LOAD_MSG_6_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m2, m7); \
+        b1 = _mm_alignr_epi8(m5, m6, 8); \
+    } while (0)
+
+#define LOAD_MSG_6_3(b0, b1)                                 \
+    do {                                                     \
+        b0 = _mm_unpacklo_epi64(m0, m3);                     \
+        b1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1, 0, 3, 2)); \
+    } while (0)
+
+#define LOAD_MSG_6_4(b0, b1)                \
+    do {                                    \
+        b0 = _mm_unpackhi_epi64(m3, m1);    \
+        b1 = _mm_blend_epi16(m1, m5, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_7_1(b0, b1)                \
+    do {                                    \
+        b0 = _mm_unpackhi_epi64(m6, m3);    \
+        b1 = _mm_blend_epi16(m6, m1, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_7_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_alignr_epi8(m7, m5, 8); \
+        b1 = _mm_unpackhi_epi64(m0, m4); \
+    } while (0)
+
+#define LOAD_MSG_7_3(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m2, m7); \
+        b1 = _mm_unpacklo_epi64(m4, m1); \
+    } while (0)
+
+#define LOAD_MSG_7_4(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m0, m2); \
+        b1 = _mm_unpacklo_epi64(m3, m5); \
+    } while (0)
+
+#define LOAD_MSG_8_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m3, m7); \
+        b1 = _mm_alignr_epi8(m0, m5, 8); \
+    } while (0)
+
+#define LOAD_MSG_8_2(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m7, m4); \
+        b1 = _mm_alignr_epi8(m4, m1, 8); \
+    } while (0)
+
+#define LOAD_MSG_8_3(b0, b1)             \
+    do {                                 \
+        b0 = m6;                         \
+        b1 = _mm_alignr_epi8(m5, m0, 8); \
+    } while (0)
+
+#define LOAD_MSG_8_4(b0, b1)                \
+    do {                                    \
+        b0 = _mm_blend_epi16(m1, m3, 0xF0); \
+        b1 = m2;                            \
+    } while (0)
+
+#define LOAD_MSG_9_1(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m5, m4); \
+        b1 = _mm_unpackhi_epi64(m3, m0); \
+    } while (0)
+
+#define LOAD_MSG_9_2(b0, b1)                \
+    do {                                    \
+        b0 = _mm_unpacklo_epi64(m1, m2);    \
+        b1 = _mm_blend_epi16(m3, m2, 0xF0); \
+    } while (0)
+
+#define LOAD_MSG_9_3(b0, b1)             \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m7, m4); \
+        b1 = _mm_unpackhi_epi64(m1, m6); \
+    } while (0)
+
+#define LOAD_MSG_9_4(b0, b1)             \
+    do {                                 \
+        b0 = _mm_alignr_epi8(m7, m5, 8); \
+        b1 = _mm_unpacklo_epi64(m6, m0); \
+    } while (0)
+
+#define LOAD_MSG_10_1(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m0, m1); \
+        b1 = _mm_unpacklo_epi64(m2, m3); \
+    } while (0)
+
+#define LOAD_MSG_10_2(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m0, m1); \
+        b1 = _mm_unpackhi_epi64(m2, m3); \
+    } while (0)
+
+#define LOAD_MSG_10_3(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m4, m5); \
+        b1 = _mm_unpacklo_epi64(m6, m7); \
+    } while (0)
+
+#define LOAD_MSG_10_4(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpackhi_epi64(m4, m5); \
+        b1 = _mm_unpackhi_epi64(m6, m7); \
+    } while (0)
+
+#define LOAD_MSG_11_1(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m7, m2); \
+        b1 = _mm_unpackhi_epi64(m4, m6); \
+    } while (0)
+
+#define LOAD_MSG_11_2(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m5, m4); \
+        b1 = _mm_alignr_epi8(m3, m7, 8); \
+    } while (0)
+
+#define LOAD_MSG_11_3(b0, b1)                                \
+    do {                                                     \
+        b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2)); \
+        b1 = _mm_unpackhi_epi64(m5, m2);                     \
+    } while (0)
+
+#define LOAD_MSG_11_4(b0, b1)            \
+    do {                                 \
+        b0 = _mm_unpacklo_epi64(m6, m1); \
+        b1 = _mm_unpackhi_epi64(m3, m1); \
+    } while (0)
+
+#endif

+ 438 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/blake2b-ref.c

@@ -0,0 +1,438 @@
+/*
+   BLAKE2 reference source code package - C implementations
+
+   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   You should have received a copy of the CC0 Public Domain Dedication along
+   with
+   this software. If not, see
+   <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "core.h"
+#include "private/common.h"
+#include "runtime.h"
+#include "utils.h"
+
+static blake2b_compress_fn blake2b_compress = blake2b_compress_ref;
+
+static const uint64_t blake2b_IV[8] = {
+    0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+    0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+    0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+/* LCOV_EXCL_START */
+static inline int
+blake2b_set_lastnode(blake2b_state *S)
+{
+    S->f[1] = -1;
+    return 0;
+}
+/* LCOV_EXCL_STOP */
+
+static inline int
+blake2b_is_lastblock(const blake2b_state *S)
+{
+    return S->f[0] != 0;
+}
+
+static inline int
+blake2b_set_lastblock(blake2b_state *S)
+{
+    if (S->last_node) {
+        blake2b_set_lastnode(S);
+    }
+    S->f[0] = -1;
+    return 0;
+}
+
+static inline int
+blake2b_increment_counter(blake2b_state *S, const uint64_t inc)
+{
+#ifdef HAVE_TI_MODE
+    uint128_t t = ((uint128_t) S->t[1] << 64) | S->t[0];
+    t += inc;
+    S->t[0] = (uint64_t)(t >> 0);
+    S->t[1] = (uint64_t)(t >> 64);
+#else
+    S->t[0] += inc;
+    S->t[1] += (S->t[0] < inc);
+#endif
+    return 0;
+}
+
+/* Parameter-related functions */
+static inline int
+blake2b_param_set_salt(blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES])
+{
+    memcpy(P->salt, salt, BLAKE2B_SALTBYTES);
+    return 0;
+}
+
+static inline int
+blake2b_param_set_personal(blake2b_param *P,
+                           const uint8_t  personal[BLAKE2B_PERSONALBYTES])
+{
+    memcpy(P->personal, personal, BLAKE2B_PERSONALBYTES);
+    return 0;
+}
+
+static inline int
+blake2b_init0(blake2b_state *S)
+{
+    int i;
+
+    for (i  = 0; i < 8; i++) {
+        S->h[i] = blake2b_IV[i];
+    }
+    /* zero everything between .t and .last_node */
+    memset((void *) &S->t, 0,
+           offsetof(blake2b_state, last_node) + sizeof(S->last_node)
+           - offsetof(blake2b_state, t));
+    return 0;
+}
+
+/* init xors IV with input parameter block */
+int
+blake2b_init_param(blake2b_state *S, const blake2b_param *P)
+{
+    size_t         i;
+    const uint8_t *p;
+
+    COMPILER_ASSERT(sizeof *P == 64);
+    blake2b_init0(S);
+    p = (const uint8_t *) (P);
+
+    /* IV XOR ParamBlock */
+    for (i = 0; i < 8; i++) {
+        S->h[i] ^= LOAD64_LE(p + sizeof(S->h[i]) * i);
+    }
+    return 0;
+}
+
+int
+blake2b_init(blake2b_state *S, const uint8_t outlen)
+{
+    blake2b_param P[1];
+
+    if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+        sodium_misuse();
+    }
+    P->digest_length = outlen;
+    P->key_length    = 0;
+    P->fanout        = 1;
+    P->depth         = 1;
+    STORE32_LE(P->leaf_length, 0);
+    STORE64_LE(P->node_offset, 0);
+    P->node_depth   = 0;
+    P->inner_length = 0;
+    memset(P->reserved, 0, sizeof(P->reserved));
+    memset(P->salt, 0, sizeof(P->salt));
+    memset(P->personal, 0, sizeof(P->personal));
+    return blake2b_init_param(S, P);
+}
+
+int
+blake2b_init_salt_personal(blake2b_state *S, const uint8_t outlen,
+                           const void *salt, const void *personal)
+{
+    blake2b_param P[1];
+
+    if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+        sodium_misuse();
+    }
+    P->digest_length = outlen;
+    P->key_length    = 0;
+    P->fanout        = 1;
+    P->depth         = 1;
+    STORE32_LE(P->leaf_length, 0);
+    STORE64_LE(P->node_offset, 0);
+    P->node_depth   = 0;
+    P->inner_length = 0;
+    memset(P->reserved, 0, sizeof(P->reserved));
+    if (salt != NULL) {
+        blake2b_param_set_salt(P, (const uint8_t *) salt);
+    } else {
+        memset(P->salt, 0, sizeof(P->salt));
+    }
+    if (personal != NULL) {
+        blake2b_param_set_personal(P, (const uint8_t *) personal);
+    } else {
+        memset(P->personal, 0, sizeof(P->personal));
+    }
+    return blake2b_init_param(S, P);
+}
+
+int
+blake2b_init_key(blake2b_state *S, const uint8_t outlen, const void *key,
+                 const uint8_t keylen)
+{
+    blake2b_param P[1];
+
+    if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+        sodium_misuse();
+    }
+    if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) {
+        sodium_misuse(); /* does not return */
+    }
+    P->digest_length = outlen;
+    P->key_length    = keylen;
+    P->fanout        = 1;
+    P->depth         = 1;
+    STORE32_LE(P->leaf_length, 0);
+    STORE64_LE(P->node_offset, 0);
+    P->node_depth   = 0;
+    P->inner_length = 0;
+    memset(P->reserved, 0, sizeof(P->reserved));
+    memset(P->salt, 0, sizeof(P->salt));
+    memset(P->personal, 0, sizeof(P->personal));
+
+    if (blake2b_init_param(S, P) < 0) {
+        sodium_misuse();
+    }
+    {
+        uint8_t block[BLAKE2B_BLOCKBYTES];
+        memset(block, 0, BLAKE2B_BLOCKBYTES);
+        memcpy(block, key, keylen); /* key and keylen cannot be 0 */
+        blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
+        sodium_memzero(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
+    }
+    return 0;
+}
+
+int
+blake2b_init_key_salt_personal(blake2b_state *S, const uint8_t outlen,
+                               const void *key, const uint8_t keylen,
+                               const void *salt, const void *personal)
+{
+    blake2b_param P[1];
+
+    if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+        sodium_misuse();
+    }
+    if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) {
+        sodium_misuse(); /* does not return */
+    }
+    P->digest_length = outlen;
+    P->key_length    = keylen;
+    P->fanout        = 1;
+    P->depth         = 1;
+    STORE32_LE(P->leaf_length, 0);
+    STORE64_LE(P->node_offset, 0);
+    P->node_depth   = 0;
+    P->inner_length = 0;
+    memset(P->reserved, 0, sizeof(P->reserved));
+    if (salt != NULL) {
+        blake2b_param_set_salt(P, (const uint8_t *) salt);
+    } else {
+        memset(P->salt, 0, sizeof(P->salt));
+    }
+    if (personal != NULL) {
+        blake2b_param_set_personal(P, (const uint8_t *) personal);
+    } else {
+        memset(P->personal, 0, sizeof(P->personal));
+    }
+
+    if (blake2b_init_param(S, P) < 0) {
+        sodium_misuse();
+    }
+    {
+        uint8_t block[BLAKE2B_BLOCKBYTES];
+        memset(block, 0, BLAKE2B_BLOCKBYTES);
+        memcpy(block, key, keylen); /* key and keylen cannot be 0 */
+        blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
+        sodium_memzero(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
+    }
+    return 0;
+}
+
+/* inlen now in bytes */
+int
+blake2b_update(blake2b_state *S, const uint8_t *in, uint64_t inlen)
+{
+    while (inlen > 0) {
+        size_t left = S->buflen;
+        size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
+
+        if (inlen > fill) {
+            memcpy(S->buf + left, in, fill); /* Fill buffer */
+            S->buflen += fill;
+            blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+            blake2b_compress(S, S->buf); /* Compress */
+            memcpy(S->buf, S->buf + BLAKE2B_BLOCKBYTES,
+                   BLAKE2B_BLOCKBYTES); /* Shift buffer left */
+            S->buflen -= BLAKE2B_BLOCKBYTES;
+            in += fill;
+            inlen -= fill;
+        } else /* inlen <= fill */
+        {
+            memcpy(S->buf + left, in, inlen);
+            S->buflen += inlen; /* Be lazy, do not compress */
+            in += inlen;
+            inlen -= inlen;
+        }
+    }
+
+    return 0;
+}
+
+int
+blake2b_final(blake2b_state *S, uint8_t *out, uint8_t outlen)
+{
+    unsigned char buffer[BLAKE2B_OUTBYTES];
+
+    if (!outlen || outlen > BLAKE2B_OUTBYTES) {
+        sodium_misuse();
+    }
+    if (blake2b_is_lastblock(S)) {
+        return -1;
+    }
+    if (S->buflen > BLAKE2B_BLOCKBYTES) {
+        blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+        blake2b_compress(S, S->buf);
+        S->buflen -= BLAKE2B_BLOCKBYTES;
+        assert(S->buflen <= BLAKE2B_BLOCKBYTES);
+        memcpy(S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen);
+    }
+
+    blake2b_increment_counter(S, S->buflen);
+    blake2b_set_lastblock(S);
+    memset(S->buf + S->buflen, 0,
+           2 * BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
+    blake2b_compress(S, S->buf);
+
+    COMPILER_ASSERT(sizeof buffer == 64U);
+    STORE64_LE(buffer + 8 * 0, S->h[0]);
+    STORE64_LE(buffer + 8 * 1, S->h[1]);
+    STORE64_LE(buffer + 8 * 2, S->h[2]);
+    STORE64_LE(buffer + 8 * 3, S->h[3]);
+    STORE64_LE(buffer + 8 * 4, S->h[4]);
+    STORE64_LE(buffer + 8 * 5, S->h[5]);
+    STORE64_LE(buffer + 8 * 6, S->h[6]);
+    STORE64_LE(buffer + 8 * 7, S->h[7]);
+    memcpy(out, buffer, outlen); /* outlen <= BLAKE2B_OUTBYTES (64) */
+
+    sodium_memzero(S->h, sizeof S->h);
+    sodium_memzero(S->buf, sizeof S->buf);
+
+    return 0;
+}
+
+/* inlen, at least, should be uint64_t. Others can be size_t. */
+int
+blake2b(uint8_t *out, const void *in, const void *key, const uint8_t outlen,
+        const uint64_t inlen, uint8_t keylen)
+{
+    CRYPTO_ALIGN(64) blake2b_state S[1];
+
+    /* Verify parameters */
+    if (NULL == in && inlen > 0) {
+        sodium_misuse();
+    }
+    if (NULL == out) {
+        sodium_misuse();
+    }
+    if (!outlen || outlen > BLAKE2B_OUTBYTES) {
+        sodium_misuse();
+    }
+    if (NULL == key && keylen > 0) {
+        sodium_misuse();
+    }
+    if (keylen > BLAKE2B_KEYBYTES) {
+        sodium_misuse();
+    }
+    if (keylen > 0) {
+        if (blake2b_init_key(S, outlen, key, keylen) < 0) {
+            sodium_misuse();
+        }
+    } else {
+        if (blake2b_init(S, outlen) < 0) {
+            sodium_misuse();
+        }
+    }
+
+    blake2b_update(S, (const uint8_t *) in, inlen);
+    blake2b_final(S, out, outlen);
+    return 0;
+}
+
+int
+blake2b_salt_personal(uint8_t *out, const void *in, const void *key,
+                      const uint8_t outlen, const uint64_t inlen,
+                      uint8_t keylen, const void *salt, const void *personal)
+{
+    CRYPTO_ALIGN(64) blake2b_state S[1];
+
+    /* Verify parameters */
+    if (NULL == in && inlen > 0) {
+        sodium_misuse();
+    }
+    if (NULL == out) {
+        sodium_misuse();
+    }
+    if (!outlen || outlen > BLAKE2B_OUTBYTES) {
+        sodium_misuse();
+    }
+    if (NULL == key && keylen > 0) {
+        sodium_misuse();
+    }
+    if (keylen > BLAKE2B_KEYBYTES) {
+        sodium_misuse();
+    }
+    if (keylen > 0) {
+        if (blake2b_init_key_salt_personal(S, outlen, key, keylen, salt,
+                                           personal) < 0) {
+            sodium_misuse();
+        }
+    } else {
+        if (blake2b_init_salt_personal(S, outlen, salt, personal) < 0) {
+            sodium_misuse();
+        }
+    }
+
+    blake2b_update(S, (const uint8_t *) in, inlen);
+    blake2b_final(S, out, outlen);
+    return 0;
+}
+
+int
+blake2b_pick_best_implementation(void)
+{
+/* LCOV_EXCL_START */
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+    defined(HAVE_SMMINTRIN_H)
+    if (sodium_runtime_has_avx2()) {
+        blake2b_compress = blake2b_compress_avx2;
+        return 0;
+    }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+    defined(HAVE_SMMINTRIN_H)
+    if (sodium_runtime_has_sse41()) {
+        blake2b_compress = blake2b_compress_sse41;
+        return 0;
+    }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+    if (sodium_runtime_has_ssse3()) {
+        blake2b_compress = blake2b_compress_ssse3;
+        return 0;
+    }
+#endif
+    blake2b_compress = blake2b_compress_ref;
+
+    return 0;
+    /* LCOV_EXCL_STOP */
+}

+ 116 - 0
Sources/Sodium/crypto_generichash/blake2b/ref/generichash_blake2b.c

@@ -0,0 +1,116 @@
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "blake2.h"
+#include "crypto_generichash_blake2b.h"
+#include "private/common.h"
+#include "private/implementations.h"
+
+int
+crypto_generichash_blake2b(unsigned char *out, size_t outlen,
+                           const unsigned char *in, unsigned long long inlen,
+                           const unsigned char *key, size_t keylen)
+{
+    if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+        keylen > BLAKE2B_KEYBYTES || inlen > UINT64_MAX) {
+        return -1;
+    }
+    assert(outlen <= UINT8_MAX);
+    assert(keylen <= UINT8_MAX);
+
+    return blake2b((uint8_t *) out, in, key, (uint8_t) outlen, (uint64_t) inlen,
+                   (uint8_t) keylen);
+}
+
+int
+crypto_generichash_blake2b_salt_personal(
+    unsigned char *out, size_t outlen, const unsigned char *in,
+    unsigned long long inlen, const unsigned char *key, size_t keylen,
+    const unsigned char *salt, const unsigned char *personal)
+{
+    if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+        keylen > BLAKE2B_KEYBYTES || inlen > UINT64_MAX) {
+        return -1;
+    }
+    assert(outlen <= UINT8_MAX);
+    assert(keylen <= UINT8_MAX);
+
+    return blake2b_salt_personal((uint8_t *) out, in, key, (uint8_t) outlen,
+                                 (uint64_t) inlen, (uint8_t) keylen, salt,
+                                 personal);
+}
+
+int
+crypto_generichash_blake2b_init(crypto_generichash_blake2b_state *state,
+                                const unsigned char *key, const size_t keylen,
+                                const size_t outlen)
+{
+    if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+        keylen > BLAKE2B_KEYBYTES) {
+        return -1;
+    }
+    assert(outlen <= UINT8_MAX);
+    assert(keylen <= UINT8_MAX);
+    COMPILER_ASSERT(sizeof(blake2b_state) <= sizeof *state);
+    if (key == NULL || keylen <= 0U) {
+        if (blake2b_init((blake2b_state *) (void *) state, (uint8_t) outlen) != 0) {
+            return -1; /* LCOV_EXCL_LINE */
+        }
+    } else if (blake2b_init_key((blake2b_state *) (void *) state, (uint8_t) outlen, key,
+                                (uint8_t) keylen) != 0) {
+        return -1; /* LCOV_EXCL_LINE */
+    }
+    return 0;
+}
+
+int
+crypto_generichash_blake2b_init_salt_personal(
+    crypto_generichash_blake2b_state *state, const unsigned char *key,
+    const size_t keylen, const size_t outlen, const unsigned char *salt,
+    const unsigned char *personal)
+{
+    if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+        keylen > BLAKE2B_KEYBYTES) {
+        return -1;
+    }
+    assert(outlen <= UINT8_MAX);
+    assert(keylen <= UINT8_MAX);
+    if (key == NULL || keylen <= 0U) {
+        if (blake2b_init_salt_personal((blake2b_state *) (void *) state,
+                                       (uint8_t) outlen, salt, personal) != 0) {
+            return -1; /* LCOV_EXCL_LINE */
+        }
+    } else if (blake2b_init_key_salt_personal((blake2b_state *) (void *) state,
+                                              (uint8_t) outlen, key,
+                                              (uint8_t) keylen, salt,
+                                              personal) != 0) {
+        return -1; /* LCOV_EXCL_LINE */
+    }
+    return 0;
+}
+
+int
+crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state,
+                                  const unsigned char *in,
+                                  unsigned long long inlen)
+{
+    return blake2b_update((blake2b_state *) (void *) state,
+                          (const uint8_t *) in, (uint64_t) inlen);
+}
+
+int
+crypto_generichash_blake2b_final(crypto_generichash_blake2b_state *state,
+                                 unsigned char *out, const size_t outlen)
+{
+    assert(outlen <= UINT8_MAX);
+    return blake2b_final((blake2b_state *) (void *) state,
+                         (uint8_t *) out, (uint8_t) outlen);
+}
+
+int
+_crypto_generichash_blake2b_pick_best_implementation(void)
+{
+    return blake2b_pick_best_implementation();
+}

Деякі файли не було показано, через те що забагато файлів було змінено