notecy 5 months ago
parent
commit
daf766a5d0
100 changed files with 14135 additions and 3586 deletions
  1. BIN
      bin/x64/debug/Keywords.db
  2. BIN
      bin/x64/debug/caching_sha2_password.dll
  3. 3 1
      include/SQLyog.rc
  4. BIN
      include/VersionInfo.rc
  5. 1 1
      include/cryptlib/adler32.h
  6. 1281 0
      include/cryptlib/adv_simd.h
  7. 1 1
      include/cryptlib/aes.h
  8. 30 0
      include/cryptlib/aes_armv4.h
  9. 21 21
      include/cryptlib/algebra.h
  10. 15 9
      include/cryptlib/algparam.h
  11. 74 0
      include/cryptlib/allocate.h
  12. 2 2
      include/cryptlib/arc4.h
  13. 1 1
      include/cryptlib/aria.h
  14. 427 0
      include/cryptlib/arm_simd.h
  15. 445 57
      include/cryptlib/asn.h
  16. 1 1
      include/cryptlib/authenc.h
  17. 19 12
      include/cryptlib/basecode.h
  18. 60 12
      include/cryptlib/bench.h
  19. 377 242
      include/cryptlib/blake2.h
  20. 16 4
      include/cryptlib/blumshub.h
  21. 4 0
      include/cryptlib/cbcmac.h
  22. 3 1
      include/cryptlib/ccm.h
  23. 183 45
      include/cryptlib/chacha.h
  24. 322 0
      include/cryptlib/chachapoly.h
  25. 179 0
      include/cryptlib/cham.h
  26. 10 0
      include/cryptlib/cmac.h
  27. 25 1164
      include/cryptlib/config.h
  28. 72 0
      include/cryptlib/config_align.h
  29. 492 0
      include/cryptlib/config_asm.h
  30. 212 0
      include/cryptlib/config_cpu.h
  31. 250 0
      include/cryptlib/config_cxx.h
  32. 178 0
      include/cryptlib/config_dll.h
  33. 268 0
      include/cryptlib/config_int.h
  34. 199 0
      include/cryptlib/config_misc.h
  35. 76 0
      include/cryptlib/config_ns.h
  36. 168 0
      include/cryptlib/config_os.h
  37. 96 0
      include/cryptlib/config_ver.h
  38. 479 168
      include/cryptlib/cpu.h
  39. 25 9
      include/cryptlib/crc.h
  40. 276 222
      include/cryptlib/cryptlib.h
  41. 95 0
      include/cryptlib/darn.h
  42. 33 33
      include/cryptlib/default.h
  43. 0 1
      include/cryptlib/dll.h
  44. 11 3
      include/cryptlib/dmac.h
  45. 179 0
      include/cryptlib/donna.h
  46. 411 0
      include/cryptlib/donna_32.h
  47. 457 0
      include/cryptlib/donna_64.h
  48. 86 0
      include/cryptlib/donna_sse.h
  49. 169 196
      include/cryptlib/drbg.h
  50. 16 5
      include/cryptlib/dsa.h
  51. 4 0
      include/cryptlib/eax.h
  52. 2 3
      include/cryptlib/ec2n.h
  53. 65 42
      include/cryptlib/eccrypto.h
  54. 18 6
      include/cryptlib/ecp.h
  55. 9 9
      include/cryptlib/ecpoint.h
  56. 175 16
      include/cryptlib/elgamal.h
  57. 12 12
      include/cryptlib/eprecomp.h
  58. 177 71
      include/cryptlib/fhmqv.h
  59. 11 7
      include/cryptlib/files.h
  60. 233 137
      include/cryptlib/filters.h
  61. 8 8
      include/cryptlib/fips140.h
  62. 3 21
      include/cryptlib/fltrimpl.h
  63. 9 1
      include/cryptlib/gcm.h
  64. 27 10
      include/cryptlib/gf2n.h
  65. 232 57
      include/cryptlib/gfpcrypt.h
  66. 3 0
      include/cryptlib/hashfwd.h
  67. 67 0
      include/cryptlib/hc128.h
  68. 69 0
      include/cryptlib/hc256.h
  69. 81 0
      include/cryptlib/hight.h
  70. 9 8
      include/cryptlib/hkdf.h
  71. 7 2
      include/cryptlib/hmac.h
  72. 185 78
      include/cryptlib/hmqv.h
  73. 77 8
      include/cryptlib/hrtimer.h
  74. 5 3
      include/cryptlib/ida.h
  75. 197 172
      include/cryptlib/integer.h
  76. 37 15
      include/cryptlib/iterhash.h
  77. 6 6
      include/cryptlib/kalyna.h
  78. 47 34
      include/cryptlib/keccak.h
  79. 108 0
      include/cryptlib/lea.h
  80. 262 0
      include/cryptlib/lsh.h
  81. 2 2
      include/cryptlib/lubyrack.h
  82. 5 3
      include/cryptlib/md2.h
  83. 48 45
      include/cryptlib/mersenne.h
  84. 516 163
      include/cryptlib/misc.h
  85. 58 37
      include/cryptlib/modarith.h
  86. 133 17
      include/cryptlib/modes.h
  87. 47 7
      include/cryptlib/mqueue.h
  88. 56 11
      include/cryptlib/mqv.h
  89. 99 78
      include/cryptlib/naclite.h
  90. 36 32
      include/cryptlib/nbtheory.h
  91. 5 0
      include/cryptlib/nr.h
  92. 45 4
      include/cryptlib/oids.h
  93. 69 42
      include/cryptlib/osrng.h
  94. 22 22
      include/cryptlib/ossig.h
  95. 5 3
      include/cryptlib/padlkrng.h
  96. 17 5
      include/cryptlib/panama.h
  97. 121 47
      include/cryptlib/poly1305.h
  98. 2764 0
      include/cryptlib/ppc_simd.h
  99. 3 3
      include/cryptlib/pssr.h
  100. 191 128
      include/cryptlib/pubkey.h

BIN
bin/x64/debug/Keywords.db


BIN
bin/x64/debug/caching_sha2_password.dll


+ 3 - 1
include/SQLyog.rc

@@ -7,7 +7,9 @@
 //
 // Generated from the TEXTINCLUDE 2 resource.
 //
-#include "afxres.h"
+//#include "afxres.h"
+#include "Windows.h"
+#include "winres.h"
 #include "Symbols.h"
 #include "AppInfo.h"
 /////////////////////////////////////////////////////////////////////////////

BIN
include/VersionInfo.rc


+ 1 - 1
include/cryptlib/adler32.h

@@ -14,7 +14,7 @@ NAMESPACE_BEGIN(CryptoPP)
 class Adler32 : public HashTransformation
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 4);
 	Adler32() {Reset();}
 	void Update(const byte *input, size_t length);
 	void TruncatedFinal(byte *hash, size_t size);

+ 1281 - 0
include/cryptlib/adv_simd.h

@@ -0,0 +1,1281 @@
+// adv_simd.h - written and placed in the public domain by Jeffrey Walton
+
+/// \file adv_simd.h
+/// \brief Template for AdvancedProcessBlocks and SIMD processing
+
+//    The SIMD based implementations for ciphers that use SSE, NEON and Power7
+//    have a common pattern. Namely, they have a specialized implementation of
+//    AdvancedProcessBlocks which processes multiple block using hardware
+//    acceleration. After several implementations we noticed a lot of copy and
+//    paste occurring. adv_simd.h provides a template to avoid the copy and paste.
+//
+//    There are 6 templates provided in this file. The number following the
+//    function name, 128, is the block size in bits. The name following the
+//    block size is the arrangement and acceleration. For example 4x1_SSE means
+//    Intel SSE using two encrypt (or decrypt) functions: one that operates on
+//    4 SIMD words, and one that operates on 1 SIMD words.
+//
+//      * AdvancedProcessBlocks128_4x1_SSE
+//      * AdvancedProcessBlocks128_6x2_SSE
+//      * AdvancedProcessBlocks128_4x1_NEON
+//      * AdvancedProcessBlocks128_6x1_NEON
+//      * AdvancedProcessBlocks128_4x1_ALTIVEC
+//      * AdvancedProcessBlocks128_6x1_ALTIVEC
+//
+//    If an arrangement ends in 2, like 6x2, then the template will handle the
+//    single block case by padding with 0's and using the two SIMD word
+//    function. This happens at most one time when processing multiple blocks.
+//    The extra processing of a zero block is trivial and worth the tradeoff.
+//
+//    The MAYBE_CONST macro present on x86 is a SunCC workaround. Some versions
+//    of SunCC lose/drop the const-ness in the F1 and F4 functions. It eventually
+//    results in a failed link due to the const/non-const mismatch.
+//
+//    In July 2020 the library stopped using 64-bit block version of
+//    AdvancedProcessBlocks. Testing showed unreliable results and failed
+//    self tests on occasion. Also see Issue 945 and
+//    https://github.com/weidai11/cryptopp/commit/dd7598e638bb.
+
+#ifndef CRYPTOPP_ADVANCED_SIMD_TEMPLATES
+#define CRYPTOPP_ADVANCED_SIMD_TEMPLATES
+
+#include "config.h"
+#include "misc.h"
+#include "stdcpp.h"
+
+#if (CRYPTOPP_ARM_NEON_HEADER)
+# include <arm_neon.h>
+#endif
+
+#if (CRYPTOPP_ARM_ACLE_HEADER)
+# include <stdint.h>
+# include <arm_acle.h>
+#endif
+
+#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
+# include <emmintrin.h>
+# include <xmmintrin.h>
+#endif
+
+// SunCC needs CRYPTOPP_SSSE3_AVAILABLE, too
+#if (CRYPTOPP_SSSE3_AVAILABLE)
+# include <emmintrin.h>
+# include <pmmintrin.h>
+# include <xmmintrin.h>
+#endif
+
+#if defined(__ALTIVEC__)
+# include "ppc_simd.h"
+#endif
+
+// ************************ All block ciphers *********************** //
+
+ANONYMOUS_NAMESPACE_BEGIN
+
+using CryptoPP::BlockTransformation;
+
+CRYPTOPP_CONSTANT(BT_XorInput = BlockTransformation::BT_XorInput);
+CRYPTOPP_CONSTANT(BT_AllowParallel = BlockTransformation::BT_AllowParallel);
+CRYPTOPP_CONSTANT(BT_InBlockIsCounter = BlockTransformation::BT_InBlockIsCounter);
+CRYPTOPP_CONSTANT(BT_ReverseDirection = BlockTransformation::BT_ReverseDirection);
+CRYPTOPP_CONSTANT(BT_DontIncrementInOutPointers = BlockTransformation::BT_DontIncrementInOutPointers);
+
+ANONYMOUS_NAMESPACE_END
+
+// *************************** ARM NEON ************************** //
+
+#if (CRYPTOPP_ARM_NEON_AVAILABLE) || (CRYPTOPP_ARM_ASIMD_AVAILABLE) || \
+    defined(CRYPTOPP_DOXYGEN_PROCESSING)
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief AdvancedProcessBlocks for 1 and 6 blocks
+/// \tparam F1 function to process 1 128-bit block
+/// \tparam F6 function to process 6 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_6x1_NEON processes 6 and 2 NEON SIMD words
+///  at a time.
+/// \details The subkey type is usually word32 or word64. F1 and F6 must use the
+///  same word type.
+template <typename F1, typename F6, typename W>
+inline size_t AdvancedProcessBlocks128_6x1_NEON(F1 func1, F6 func6,
+            const W *subKeys, size_t rounds, const byte *inBlocks,
+            const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+    const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
+    const uint32x4_t s_one = vld1q_u32(w_one);
+
+    const size_t blockSize = 16;
+    // const size_t neonBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 6*blockSize)
+        {
+            uint64x2_t block0, block1, block2, block3, block4, block5;
+            if (flags & BT_InBlockIsCounter)
+            {
+                const uint64x2_t one = vreinterpretq_u64_u32(s_one);
+                block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                block1 = vaddq_u64(block0, one);
+                block2 = vaddq_u64(block1, one);
+                block3 = vaddq_u64(block2, one);
+                block4 = vaddq_u64(block3, one);
+                block5 = vaddq_u64(block4, one);
+                vst1q_u8(const_cast<byte*>(inBlocks),
+                    vreinterpretq_u8_u64(vaddq_u64(block5, one)));
+            }
+            else
+            {
+                block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block4 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block5 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = veorq_u64(block2, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = veorq_u64(block3, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = veorq_u64(block4, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = veorq_u64(block5, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func6(block0, block1, block2, block3, block4, block5, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = veorq_u64(block2, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = veorq_u64(block3, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = veorq_u64(block4, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = veorq_u64(block5, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block0));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block1));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block2));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block3));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block4));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block5));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 6*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        uint64x2_t block;
+        block = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+
+        if (xorInput)
+            block = veorq_u64(block, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func1(block, subKeys, static_cast<unsigned int>(rounds));
+
+        if (xorOutput)
+            block = veorq_u64(block, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+
+        vst1q_u8(outBlocks, vreinterpretq_u8_u64(block));
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+/// \brief AdvancedProcessBlocks for 1 and 4 blocks
+/// \tparam F1 function to process 1 128-bit block
+/// \tparam F4 function to process 4 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_4x1_NEON processes 4 and 1 NEON SIMD words
+///  at a time.
+/// \details The subkey type is usually word32 or word64. V is the vector type and it is
+///  usually uint32x4_t or uint32x4_t. F1, F4, and W must use the same word and
+///  vector type.
+template <typename F1, typename F4, typename W>
+inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4,
+            const W *subKeys, size_t rounds, const byte *inBlocks,
+            const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+    const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
+    const uint32x4_t s_one = vld1q_u32(w_one);
+
+    const size_t blockSize = 16;
+    // const size_t neonBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 4*blockSize)
+        {
+            uint32x4_t block0, block1, block2, block3;
+            if (flags & BT_InBlockIsCounter)
+            {
+                const uint32x4_t one = s_one;
+                block0 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
+                block1 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block0), vreinterpretq_u64_u32(one)));
+                block2 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block1), vreinterpretq_u64_u32(one)));
+                block3 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block2), vreinterpretq_u64_u32(one)));
+                vst1q_u8(const_cast<byte*>(inBlocks), vreinterpretq_u8_u64(vaddq_u64(
+                    vreinterpretq_u64_u32(block3), vreinterpretq_u64_u32(one))));
+            }
+            else
+            {
+                block0 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = veorq_u32(block0, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u32(block1, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = veorq_u32(block2, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = veorq_u32(block3, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func4(block0, block1, block2, block3, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = veorq_u32(block0, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u32(block1, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = veorq_u32(block2, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = veorq_u32(block3, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            vst1q_u8(outBlocks, vreinterpretq_u8_u32(block0));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u32(block1));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u32(block2));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u32(block3));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 4*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        uint32x4_t block = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
+
+        if (xorInput)
+            block = veorq_u32(block, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func1(block, subKeys, static_cast<unsigned int>(rounds));
+
+        if (xorOutput)
+            block = veorq_u32(block, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
+
+        vst1q_u8(outBlocks, vreinterpretq_u8_u32(block));
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+/// \brief AdvancedProcessBlocks for 2 and 6 blocks
+/// \tparam F2 function to process 2 128-bit blocks
+/// \tparam F6 function to process 6 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_6x2_NEON processes 6 and 2 NEON SIMD words
+///  at a time. For a single block the template uses F2 with a zero block.
+/// \details The subkey type is usually word32 or word64. F2 and F6 must use the
+///  same word type.
+template <typename F2, typename F6, typename W>
+inline size_t AdvancedProcessBlocks128_6x2_NEON(F2 func2, F6 func6,
+            const W *subKeys, size_t rounds, const byte *inBlocks,
+            const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+    const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
+    const uint32x4_t s_one = vld1q_u32(w_one);
+
+    const size_t blockSize = 16;
+    // const size_t neonBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 6*blockSize)
+        {
+            uint64x2_t block0, block1, block2, block3, block4, block5;
+            if (flags & BT_InBlockIsCounter)
+            {
+                const uint64x2_t one = vreinterpretq_u64_u32(s_one);
+                block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                block1 = vaddq_u64(block0, one);
+                block2 = vaddq_u64(block1, one);
+                block3 = vaddq_u64(block2, one);
+                block4 = vaddq_u64(block3, one);
+                block5 = vaddq_u64(block4, one);
+                vst1q_u8(const_cast<byte*>(inBlocks),
+                    vreinterpretq_u8_u64(vaddq_u64(block5, one)));
+            }
+            else
+            {
+                block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block4 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block5 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = veorq_u64(block2, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = veorq_u64(block3, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = veorq_u64(block4, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = veorq_u64(block5, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func6(block0, block1, block2, block3, block4, block5, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = veorq_u64(block2, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = veorq_u64(block3, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = veorq_u64(block4, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = veorq_u64(block5, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block0));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block1));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block2));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block3));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block4));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block5));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 6*blockSize;
+        }
+
+        while (length >= 2*blockSize)
+        {
+            uint64x2_t block0, block1;
+            if (flags & BT_InBlockIsCounter)
+            {
+                const uint64x2_t one = vreinterpretq_u64_u32(s_one);
+                block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                block1 = vaddq_u64(block0, one);
+                vst1q_u8(const_cast<byte*>(inBlocks),
+                    vreinterpretq_u8_u64(vaddq_u64(block1, one)));
+            }
+            else
+            {
+                block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func2(block0, block1, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block0));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            vst1q_u8(outBlocks, vreinterpretq_u8_u64(block1));
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 2*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        uint64x2_t block, zero = {0,0};
+        block = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
+
+        if (xorInput)
+            block = veorq_u64(block, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func2(block, zero, subKeys, static_cast<unsigned int>(rounds));
+
+        if (xorOutput)
+            block = veorq_u64(block, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
+
+        vst1q_u8(outBlocks, vreinterpretq_u8_u64(block));
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+NAMESPACE_END  // CryptoPP
+
+#endif  // CRYPTOPP_ARM_NEON_AVAILABLE
+
+// *************************** Intel SSE ************************** //
+
+#if defined(CRYPTOPP_SSSE3_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief SunCC workaround
+/// \details SunCC loses the const on AES_Enc_Block and AES_Dec_Block
+/// \sa <A HREF="http://github.com/weidai11/cryptopp/issues/224">Issue
+///  224, SunCC and failed compile for rijndael.cpp</A>
+# define MAYBE_CONST const
+/// \brief SunCC workaround
+/// \details SunCC loses the const on AES_Enc_Block and AES_Dec_Block
+/// \sa <A HREF="http://github.com/weidai11/cryptopp/issues/224">Issue
+///  224, SunCC and failed compile for rijndael.cpp</A>
+# define MAYBE_UNCONST_CAST(T, x) (x)
+#elif (__SUNPRO_CC >= 0x5130)
+# define MAYBE_CONST
+# define MAYBE_UNCONST_CAST(T, x) const_cast<MAYBE_CONST T>(x)
+#else
+# define MAYBE_CONST const
+# define MAYBE_UNCONST_CAST(T, x) (x)
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Clang workaround
+/// \details Clang issues spurious alignment warnings
+/// \sa <A HREF="http://bugs.llvm.org/show_bug.cgi?id=20670">Issue
+///  20670, _mm_loadu_si128 parameter has wrong type</A>
+# define M128_CAST(x) ((__m128i *)(void *)(x))
+/// \brief Clang workaround
+/// \details Clang issues spurious alignment warnings
+/// \sa <A HREF="http://bugs.llvm.org/show_bug.cgi?id=20670">Issue
+///  20670, _mm_loadu_si128 parameter has wrong type</A>
+# define CONST_M128_CAST(x) ((const __m128i *)(const void *)(x))
+#else
+# ifndef M128_CAST
+#  define M128_CAST(x) ((__m128i *)(void *)(x))
+# endif
+# ifndef CONST_M128_CAST
+#  define CONST_M128_CAST(x) ((const __m128i *)(const void *)(x))
+# endif
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief AdvancedProcessBlocks for 2 and 6 blocks
+/// \tparam F2 function to process 2 128-bit blocks
+/// \tparam F6 function to process 6 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_6x2_SSE processes 6 and 2 SSE SIMD words
+///  at a time. For a single block the template uses F2 with a zero block.
+/// \details The subkey type is usually word32 or word64. F2 and F6 must use the
+///  same word type.
+template <typename F2, typename F6, typename W>
+inline size_t AdvancedProcessBlocks128_6x2_SSE(F2 func2, F6 func6,
+        MAYBE_CONST W *subKeys, size_t rounds, const byte *inBlocks,
+        const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+    const size_t blockSize = 16;
+    // const size_t xmmBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 6*blockSize)
+        {
+            __m128i block0, block1, block2, block3, block4, block5;
+            if (flags & BT_InBlockIsCounter)
+            {
+                // Increment of 1 in big-endian compatible with the ctr byte array.
+                const __m128i s_one = _mm_set_epi32(1<<24, 0, 0, 0);
+                block0 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                block1 = _mm_add_epi32(block0, s_one);
+                block2 = _mm_add_epi32(block1, s_one);
+                block3 = _mm_add_epi32(block2, s_one);
+                block4 = _mm_add_epi32(block3, s_one);
+                block5 = _mm_add_epi32(block4, s_one);
+                _mm_storeu_si128(M128_CAST(inBlocks), _mm_add_epi32(block5, s_one));
+            }
+            else
+            {
+                block0 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block4 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block5 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = _mm_xor_si128(block0, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = _mm_xor_si128(block1, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = _mm_xor_si128(block2, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = _mm_xor_si128(block3, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = _mm_xor_si128(block4, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = _mm_xor_si128(block5, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func6(block0, block1, block2, block3, block4, block5, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = _mm_xor_si128(block0, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = _mm_xor_si128(block1, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = _mm_xor_si128(block2, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = _mm_xor_si128(block3, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = _mm_xor_si128(block4, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = _mm_xor_si128(block5, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            _mm_storeu_si128(M128_CAST(outBlocks), block0);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block1);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block2);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block3);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block4);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block5);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 6*blockSize;
+        }
+
+        while (length >= 2*blockSize)
+        {
+            __m128i block0, block1;
+            if (flags & BT_InBlockIsCounter)
+            {
+                // Increment of 1 in big-endian compatible with the ctr byte array.
+                const __m128i s_one = _mm_set_epi32(1<<24, 0, 0, 0);
+                block0 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                block1 = _mm_add_epi32(block0, s_one);
+                _mm_storeu_si128(M128_CAST(inBlocks), _mm_add_epi32(block1, s_one));
+            }
+            else
+            {
+                block0 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = _mm_xor_si128(block0, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = _mm_xor_si128(block1, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func2(block0, block1, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = _mm_xor_si128(block0, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = _mm_xor_si128(block1, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            _mm_storeu_si128(M128_CAST(outBlocks), block0);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block1);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 2*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        __m128i block, zero = _mm_setzero_si128();
+        block = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+
+        if (xorInput)
+            block = _mm_xor_si128(block, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func2(block, zero, subKeys, static_cast<unsigned int>(rounds));
+
+        if (xorOutput)
+            block = _mm_xor_si128(block, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+
+        _mm_storeu_si128(M128_CAST(outBlocks), block);
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+/// \brief AdvancedProcessBlocks for 1 and 4 blocks
+/// \tparam F1 function to process 1 128-bit block
+/// \tparam F4 function to process 4 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_4x1_SSE processes 4 and 1 SSE SIMD words
+///  at a time.
+/// \details The subkey type is usually word32 or word64. F1 and F4 must use the
+///  same word type.
+template <typename F1, typename F4, typename W>
+inline size_t AdvancedProcessBlocks128_4x1_SSE(F1 func1, F4 func4,
+        MAYBE_CONST W *subKeys, size_t rounds, const byte *inBlocks,
+        const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+    const size_t blockSize = 16;
+    // const size_t xmmBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 4*blockSize)
+        {
+            __m128i block0, block1, block2, block3;
+            if (flags & BT_InBlockIsCounter)
+            {
+                // Increment of 1 in big-endian compatible with the ctr byte array.
+                const __m128i s_one = _mm_set_epi32(1<<24, 0, 0, 0);
+                block0 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                block1 = _mm_add_epi32(block0, s_one);
+                block2 = _mm_add_epi32(block1, s_one);
+                block3 = _mm_add_epi32(block2, s_one);
+                _mm_storeu_si128(M128_CAST(inBlocks), _mm_add_epi32(block3, s_one));
+            }
+            else
+            {
+                block0 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = _mm_xor_si128(block0, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = _mm_xor_si128(block1, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = _mm_xor_si128(block2, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = _mm_xor_si128(block3, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func4(block0, block1, block2, block3, subKeys, static_cast<unsigned int>(rounds));
+
+            if (xorOutput)
+            {
+                block0 = _mm_xor_si128(block0, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = _mm_xor_si128(block1, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = _mm_xor_si128(block2, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = _mm_xor_si128(block3, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            _mm_storeu_si128(M128_CAST(outBlocks), block0);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block1);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block2);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            _mm_storeu_si128(M128_CAST(outBlocks), block3);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 4*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        __m128i block = _mm_loadu_si128(CONST_M128_CAST(inBlocks));
+
+        if (xorInput)
+            block = _mm_xor_si128(block, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func1(block, subKeys, static_cast<unsigned int>(rounds));
+
+        if (xorOutput)
+            block = _mm_xor_si128(block, _mm_loadu_si128(CONST_M128_CAST(xorBlocks)));
+
+        _mm_storeu_si128(M128_CAST(outBlocks), block);
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+NAMESPACE_END  // CryptoPP
+
+#endif  // CRYPTOPP_SSSE3_AVAILABLE
+
+// ************************** Altivec/Power 4 ************************** //
+
+#if defined(__ALTIVEC__) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief AdvancedProcessBlocks for 1 and 4 blocks
+/// \tparam F1 function to process 1 128-bit block
+/// \tparam F4 function to process 4 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_4x1_ALTIVEC processes 4 and 1 Altivec SIMD words
+///  at a time.
+/// \details The subkey type is usually word32 or word64. F1 and F4 must use the
+///  same word type.
+template <typename F1, typename F4, typename W>
+inline size_t AdvancedProcessBlocks128_4x1_ALTIVEC(F1 func1, F4 func4,
+        const W *subKeys, size_t rounds, const byte *inBlocks,
+        const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+#if (CRYPTOPP_LITTLE_ENDIAN)
+    const uint32x4_p s_one  = {1,0,0,0};
+#else
+    const uint32x4_p s_one = {0,0,0,1};
+#endif
+
+    const size_t blockSize = 16;
+    // const size_t simdBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 4*blockSize)
+        {
+            uint32x4_p block0, block1, block2, block3;
+
+            if (flags & BT_InBlockIsCounter)
+            {
+                block0 = VecLoadBE(inBlocks);
+                block1 = VecAdd(block0, s_one);
+                block2 = VecAdd(block1, s_one);
+                block3 = VecAdd(block2, s_one);
+
+                // Hack due to big-endian loads used by POWER8 (and maybe ARM-BE).
+                // CTR_ModePolicy::OperateKeystream is wired such that after
+                // returning from this function CTR_ModePolicy will detect wrap on
+                // on the last counter byte and increment the next to last byte.
+                // The problem is, with a big-endian load, inBlocks[15] is really
+                // located at index 15. The vector addition using a 32-bit element
+                // generates a carry into inBlocks[14] and then CTR_ModePolicy
+                // increments inBlocks[14] too.
+                const_cast<byte*>(inBlocks)[15] += 6;
+            }
+            else
+            {
+                block0 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = VecXor(block0, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = VecXor(block1, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = VecXor(block2, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = VecXor(block3, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func4(block0, block1, block2, block3, subKeys, rounds);
+
+            if (xorOutput)
+            {
+                block0 = VecXor(block0, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = VecXor(block1, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = VecXor(block2, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = VecXor(block3, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            VecStoreBE(block0, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block1, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block2, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block3, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 4*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        uint32x4_p block = VecLoadBE(inBlocks);
+
+        if (xorInput)
+            block = VecXor(block, VecLoadBE(xorBlocks));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func1(block, subKeys, rounds);
+
+        if (xorOutput)
+            block = VecXor(block, VecLoadBE(xorBlocks));
+
+        VecStoreBE(block, outBlocks);
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+/// \brief AdvancedProcessBlocks for 1 and 6 blocks
+/// \tparam F1 function to process 1 128-bit block
+/// \tparam F6 function to process 6 128-bit blocks
+/// \tparam W word type of the subkey table
+/// \details AdvancedProcessBlocks128_6x1_ALTIVEC processes 6 and 1 Altivec SIMD words
+///  at a time.
+/// \details The subkey type is usually word32 or word64. F1 and F6 must use the
+///  same word type.
+template <typename F1, typename F6, typename W>
+inline size_t AdvancedProcessBlocks128_6x1_ALTIVEC(F1 func1, F6 func6,
+        const W *subKeys, size_t rounds, const byte *inBlocks,
+        const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+    CRYPTOPP_ASSERT(subKeys);
+    CRYPTOPP_ASSERT(inBlocks);
+    CRYPTOPP_ASSERT(outBlocks);
+    CRYPTOPP_ASSERT(length >= 16);
+
+#if (CRYPTOPP_LITTLE_ENDIAN)
+    const uint32x4_p s_one  = {1,0,0,0};
+#else
+    const uint32x4_p s_one = {0,0,0,1};
+#endif
+
+    const size_t blockSize = 16;
+    // const size_t simdBlockSize = 16;
+
+    size_t inIncrement = (flags & (EnumToInt(BT_InBlockIsCounter)|EnumToInt(BT_DontIncrementInOutPointers))) ? 0 : blockSize;
+    size_t xorIncrement = (xorBlocks != NULLPTR) ? blockSize : 0;
+    size_t outIncrement = (flags & EnumToInt(BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+
+    // Clang and Coverity are generating findings using xorBlocks as a flag.
+    const bool xorInput = (xorBlocks != NULLPTR) && (flags & EnumToInt(BT_XorInput));
+    const bool xorOutput = (xorBlocks != NULLPTR) && !(flags & EnumToInt(BT_XorInput));
+
+    if (flags & BT_ReverseDirection)
+    {
+        inBlocks = PtrAdd(inBlocks, length - blockSize);
+        xorBlocks = PtrAdd(xorBlocks, length - blockSize);
+        outBlocks = PtrAdd(outBlocks, length - blockSize);
+        inIncrement = 0-inIncrement;
+        xorIncrement = 0-xorIncrement;
+        outIncrement = 0-outIncrement;
+    }
+
+    if (flags & BT_AllowParallel)
+    {
+        while (length >= 6*blockSize)
+        {
+            uint32x4_p block0, block1, block2, block3, block4, block5;
+
+            if (flags & BT_InBlockIsCounter)
+            {
+                block0 = VecLoadBE(inBlocks);
+                block1 = VecAdd(block0, s_one);
+                block2 = VecAdd(block1, s_one);
+                block3 = VecAdd(block2, s_one);
+                block4 = VecAdd(block3, s_one);
+                block5 = VecAdd(block4, s_one);
+
+                // Hack due to big-endian loads used by POWER8 (and maybe ARM-BE).
+                // CTR_ModePolicy::OperateKeystream is wired such that after
+                // returning from this function CTR_ModePolicy will detect wrap on
+                // on the last counter byte and increment the next to last byte.
+                // The problem is, with a big-endian load, inBlocks[15] is really
+                // located at index 15. The vector addition using a 32-bit element
+                // generates a carry into inBlocks[14] and then CTR_ModePolicy
+                // increments inBlocks[14] too.
+                //
+                // To find this bug we needed a test case with a ctr of 0xNN...FA.
+                // The last octet is 0xFA and adding 6 creates the wrap to trigger
+                // the issue. If the last octet was 0xFC then 4 would trigger it.
+                // We dumb-lucked into the test with SPECK-128. The test case of
+                // interest is the one with IV 348ECA9766C09F04 826520DE47A212FA.
+                uint8x16_p temp = VecAdd((uint8x16_p)block5, (uint8x16_p)s_one);
+                VecStoreBE(temp, const_cast<byte*>(inBlocks));
+            }
+            else
+            {
+                block0 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block1 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block2 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block3 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block4 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+                block5 = VecLoadBE(inBlocks);
+                inBlocks = PtrAdd(inBlocks, inIncrement);
+            }
+
+            if (xorInput)
+            {
+                block0 = VecXor(block0, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = VecXor(block1, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = VecXor(block2, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = VecXor(block3, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = VecXor(block4, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = VecXor(block5, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            func6(block0, block1, block2, block3, block4, block5, subKeys, rounds);
+
+            if (xorOutput)
+            {
+                block0 = VecXor(block0, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block1 = VecXor(block1, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block2 = VecXor(block2, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block3 = VecXor(block3, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block4 = VecXor(block4, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+                block5 = VecXor(block5, VecLoadBE(xorBlocks));
+                xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+            }
+
+            VecStoreBE(block0, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block1, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block2, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block3, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block4, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+            VecStoreBE(block5, outBlocks);
+            outBlocks = PtrAdd(outBlocks, outIncrement);
+
+            length -= 6*blockSize;
+        }
+    }
+
+    while (length >= blockSize)
+    {
+        uint32x4_p block = VecLoadBE(inBlocks);
+
+        if (xorInput)
+            block = VecXor(block, VecLoadBE(xorBlocks));
+
+        if (flags & BT_InBlockIsCounter)
+            const_cast<byte *>(inBlocks)[15]++;
+
+        func1(block, subKeys, rounds);
+
+        if (xorOutput)
+            block = VecXor(block, VecLoadBE(xorBlocks));
+
+        VecStoreBE(block, outBlocks);
+
+        inBlocks = PtrAdd(inBlocks, inIncrement);
+        outBlocks = PtrAdd(outBlocks, outIncrement);
+        xorBlocks = PtrAdd(xorBlocks, xorIncrement);
+        length -= blockSize;
+    }
+
+    return length;
+}
+
+NAMESPACE_END  // CryptoPP
+
+#endif  // __ALTIVEC__
+
+#endif  // CRYPTOPP_ADVANCED_SIMD_TEMPLATES

+ 1 - 1
include/cryptlib/aes.h

@@ -20,7 +20,7 @@ NAMESPACE_BEGIN(CryptoPP)
 /// \sa <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
 /// \since Rijndael since Crypto++ 3.1, Intel AES-NI since Crypto++ 5.6.1, ARMv8 AES since Crypto++ 6.0,
 ///   Power8 AES since Crypto++ 6.0
-DOCUMENTED_TYPEDEF(Rijndael, AES)
+DOCUMENTED_TYPEDEF(Rijndael, AES);
 
 typedef RijndaelEncryption AESEncryption;
 typedef RijndaelDecryption AESDecryption;

+ 30 - 0
include/cryptlib/aes_armv4.h

@@ -0,0 +1,30 @@
+/* Header file for use with Cryptogam's ARMv4 AES.         */
+/* Also see http://www.openssl.org/~appro/cryptogams/ and  */
+/* https://wiki.openssl.org/index.php?title=Cryptogams_AES */
+
+#ifndef CRYPTOGAMS_AES_ARMV4_H
+#define CRYPTOGAMS_AES_ARMV4_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define AES_MAXNR 14
+//typedef struct AES_KEY_st {
+//    unsigned int rd_key[4 * (AES_MAXNR + 1)];
+//    int rounds;
+//} AES_KEY;
+
+// Instead of AES_KEY we use a 'word32 rkey[4*15+4]'. It has space for
+// both the AES_MAXNR round keys and the number of rounds in the tail.
+
+int cryptogams_AES_set_encrypt_key(const unsigned char *userKey, const int bits, unsigned int *rkey);
+int cryptogams_AES_set_decrypt_key(const unsigned char *userKey, const int bits, unsigned int *rkey);
+void cryptogams_AES_encrypt_block(const unsigned char *in, unsigned char *out, const unsigned int *rkey);
+void cryptogams_AES_decrypt_block(const unsigned char *in, unsigned char *out, const unsigned int *rkey);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* CRYPTOGAMS_AES_ARMV4_H */

+ 21 - 21
include/cryptlib/algebra.h

@@ -33,56 +33,56 @@ public:
 	/// \brief Compare two elements for equality
 	/// \param a first element
 	/// \param b second element
-	/// \returns true if the elements are equal, false otherwise
+	/// \return true if the elements are equal, false otherwise
 	/// \details Equal() tests the elements for equality using <tt>a==b</tt>
 	virtual bool Equal(const Element &a, const Element &b) const =0;
 
 	/// \brief Provides the Identity element
-	/// \returns the Identity element
+	/// \return the Identity element
 	virtual const Element& Identity() const =0;
 
 	/// \brief Adds elements in the group
 	/// \param a first element
 	/// \param b second element
-	/// \returns the sum of <tt>a</tt> and <tt>b</tt>
+	/// \return the sum of <tt>a</tt> and <tt>b</tt>
 	virtual const Element& Add(const Element &a, const Element &b) const =0;
 
 	/// \brief Inverts the element in the group
 	/// \param a first element
-	/// \returns the inverse of the element
+	/// \return the inverse of the element
 	virtual const Element& Inverse(const Element &a) const =0;
 
 	/// \brief Determine if inversion is fast
-	/// \returns true if inversion is fast, false otherwise
+	/// \return true if inversion is fast, false otherwise
 	virtual bool InversionIsFast() const {return false;}
 
 	/// \brief Doubles an element in the group
 	/// \param a the element
-	/// \returns the element doubled
+	/// \return the element doubled
 	virtual const Element& Double(const Element &a) const;
 
 	/// \brief Subtracts elements in the group
 	/// \param a first element
 	/// \param b second element
-	/// \returns the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
+	/// \return the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
 	virtual const Element& Subtract(const Element &a, const Element &b) const;
 
 	/// \brief TODO
 	/// \param a first element
 	/// \param b second element
-	/// \returns TODO
+	/// \return TODO
 	virtual Element& Accumulate(Element &a, const Element &b) const;
 
 	/// \brief Reduces an element in the congruence class
 	/// \param a element to reduce
 	/// \param b the congruence class
-	/// \returns the reduced element
+	/// \return the reduced element
 	virtual Element& Reduce(Element &a, const Element &b) const;
 
 	/// \brief Performs a scalar multiplication
 	/// \param a multiplicand
 	/// \param e multiplier
-	/// \returns the product
+	/// \return the product
 	virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
 
 	/// \brief TODO
@@ -90,7 +90,7 @@ public:
 	/// \param e1 the first multiplier
 	/// \param y second multiplicand
 	/// \param e2 the second multiplier
-	/// \returns TODO
+	/// \return TODO
 	virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
 
 	/// \brief Multiplies a base to multiple exponents in a group
@@ -135,17 +135,17 @@ public:
 
 	/// \brief Determines whether an element is a unit in the group
 	/// \param a the element
-	/// \returns true if the element is a unit after reduction, false otherwise.
+	/// \return true if the element is a unit after reduction, false otherwise.
 	virtual bool IsUnit(const Element &a) const =0;
 
 	/// \brief Retrieves the multiplicative identity
-	/// \returns the multiplicative identity
+	/// \return the multiplicative identity
 	virtual const Element& MultiplicativeIdentity() const =0;
 
 	/// \brief Multiplies elements in the group
 	/// \param a the multiplicand
 	/// \param b the multiplier
-	/// \returns the product of a and b
+	/// \return the product of a and b
 	virtual const Element& Multiply(const Element &a, const Element &b) const =0;
 
 	/// \brief Calculate the multiplicative inverse of an element in the group
@@ -154,19 +154,19 @@ public:
 
 	/// \brief Square an element in the group
 	/// \param a the element
-	/// \returns the element squared
+	/// \return the element squared
 	virtual const Element& Square(const Element &a) const;
 
 	/// \brief Divides elements in the group
 	/// \param a the dividend
 	/// \param b the divisor
-	/// \returns the quotient
+	/// \return the quotient
 	virtual const Element& Divide(const Element &a, const Element &b) const;
 
 	/// \brief Raises a base to an exponent in the group
 	/// \param a the base
 	/// \param e the exponent
-	/// \returns the exponentiation
+	/// \return the exponentiation
 	virtual Element Exponentiate(const Element &a, const Integer &e) const;
 
 	/// \brief TODO
@@ -174,7 +174,7 @@ public:
 	/// \param e1 first exponent
 	/// \param y second element
 	/// \param e2 second exponent
-	/// \returns TODO
+	/// \return TODO
 	virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
 
 	/// \brief Exponentiates a base to multiple exponents in the Ring
@@ -190,7 +190,7 @@ public:
 	virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
 
 	/// \brief Retrieves the multiplicative group
-	/// \returns the multiplicative group
+	/// \return the multiplicative group
 	virtual const AbstractGroup<T>& MultiplicativeGroup() const
 		{return m_mg;}
 
@@ -288,13 +288,13 @@ public:
 	/// \brief Performs a modular reduction in the ring
 	/// \param a the element
 	/// \param b the modulus
-	/// \returns the result of <tt>a%b</tt>.
+	/// \return the result of <tt>a%b</tt>.
 	virtual const Element& Mod(const Element &a, const Element &b) const =0;
 
 	/// \brief Calculates the greatest common denominator in the ring
 	/// \param a the first element
 	/// \param b the second element
-	/// \returns the the greatest common denominator of a and b.
+	/// \return the greatest common denominator of a and b.
 	virtual const Element& Gcd(const Element &a, const Element &b) const;
 
 protected:

+ 15 - 9
include/cryptlib/algparam.h

@@ -14,6 +14,10 @@
 #include "integer.h"
 #include "misc.h"
 
+#include <string>
+#include <typeinfo>
+#include <exception>
+
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief Used to pass byte array input as part of a NameValuePairs object
@@ -28,7 +32,7 @@ public:
 	ConstByteArrayParameter(const char *data = NULLPTR, bool deepCopy = false)
 		: m_deepCopy(false), m_data(NULLPTR), m_size(0)
 	{
-		Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
+		Assign(reinterpret_cast<const byte *>(data), data ? strlen(data) : 0, deepCopy);
 	}
 
 	/// \brief Construct a ConstByteArrayParameter
@@ -44,8 +48,8 @@ public:
 	}
 
 	/// \brief Construct a ConstByteArrayParameter
-	/// \tparam T a std::basic_string<char> class
-	/// \param string a std::basic_string<char> class
+	/// \tparam T a std::basic_string<char> or std::vector<byte> class
+	/// \param string a std::basic_string<char> or std::vector<byte> object
 	/// \param deepCopy flag indicating whether the data should be copied
 	/// \details The deepCopy option is used when the NameValuePairs object can't
 	///   keep a copy of the data available
@@ -53,7 +57,7 @@ public:
 		: m_deepCopy(false), m_data(NULLPTR), m_size(0)
 	{
 		CRYPTOPP_COMPILE_ASSERT(sizeof(typename T::value_type) == 1);
-		Assign((const byte *)string.data(), string.size(), deepCopy);
+		Assign(reinterpret_cast<const byte *>(&string[0]), string.size(), deepCopy);
 	}
 
 	/// \brief Assign contents from a memory buffer
@@ -309,9 +313,9 @@ public:
 	virtual ~AlgorithmParametersBase() CRYPTOPP_THROW
 	{
 
-#if defined(CRYPTOPP_CXX17_EXCEPTIONS)
+#if defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS)
 		if (std::uncaught_exceptions() == 0)
-#elif defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
+#elif defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION)
 		if (std::uncaught_exception() == false)
 #else
 		try
@@ -320,10 +324,12 @@ public:
 			if (m_throwIfNotUsed && !m_used)
 				throw ParameterNotUsed(m_name);
 		}
-#if !defined(CRYPTOPP_CXX17_EXCEPTIONS) && !defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
+#if !defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION)
+# if !defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS)
 		catch(const Exception&)
 		{
 		}
+# endif
 #endif
 	}
 
@@ -387,7 +393,7 @@ public:
 		}
 	}
 
-#if defined(DEBUG_NEW) && (_MSC_VER >= 1300)
+#if defined(DEBUG_NEW) && (CRYPTOPP_MSC_VERSION >= 1300)
 # pragma push_macro("new")
 # undef new
 #endif
@@ -398,7 +404,7 @@ public:
 		CRYPTOPP_UNUSED(p);	// silence warning
 	}
 
-#if defined(DEBUG_NEW) && (_MSC_VER >= 1300)
+#if defined(DEBUG_NEW) && (CRYPTOPP_MSC_VERSION >= 1300)
 # pragma pop_macro("new")
 #endif
 

+ 74 - 0
include/cryptlib/allocate.h

@@ -0,0 +1,74 @@
+// allocate.h - written and placed in the public domain by Jeffrey Walton
+
+// The functions in allocate.h and allocate.cpp were originally in misc.h
+// and misc.cpp. They were extracted in September 2019 to sidestep a circular
+// dependency with misc.h and secblock.h.
+
+/// \file allocate.h
+/// \brief Functions for allocating aligned buffers
+
+#ifndef CRYPTOPP_ALLOCATE_H
+#define CRYPTOPP_ALLOCATE_H
+
+#include "config.h"
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief Attempts to reclaim unused memory
+/// \throw bad_alloc
+/// \details In the normal course of running a program, a request for memory
+///  normally succeeds. If a call to AlignedAllocate or UnalignedAllocate fails,
+///  then CallNewHandler is called in n effort to recover. Internally,
+///  CallNewHandler calls set_new_handler(nullptr) in an effort to free memory.
+///  There is no guarantee CallNewHandler will be able to obtain more memory so
+///  an allocation succeeds. If the call to set_new_handler fails, then CallNewHandler
+///  throws a bad_alloc exception.
+/// \throw bad_alloc on failure
+/// \since Crypto++ 5.0
+/// \sa AlignedAllocate, AlignedDeallocate, UnalignedAllocate, UnalignedDeallocate
+CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
+
+/// \brief Allocates a buffer on 16-byte boundary
+/// \param size the size of the buffer
+/// \details AlignedAllocate is primarily used when the data will be
+///  processed by SSE, NEON, ARMv8 or PowerPC instructions. The assembly
+///  language routines rely on the alignment. If the alignment is not
+///  respected, then a SIGBUS could be generated on Unix and Linux, and an
+///  EXCEPTION_DATATYPE_MISALIGNMENT could be generated on Windows.
+/// \details Formerly, AlignedAllocate and AlignedDeallocate were only
+///  available on certain platforms when CRYTPOPP_DISABLE_ASM was not in
+///  effect. However, Android and iOS debug simulator builds got into a
+///  state where the aligned allocator was not available and caused link
+///  failures.
+/// \since AlignedAllocate for SIMD since Crypto++ 1.0, AlignedAllocate
+///  for all builds since Crypto++ 8.1
+/// \sa AlignedDeallocate, UnalignedAllocate, UnalignedDeallocate, CallNewHandler,
+///  <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
+CRYPTOPP_DLL void* CRYPTOPP_API AlignedAllocate(size_t size);
+
+/// \brief Frees a buffer allocated with AlignedAllocate
+/// \param ptr the buffer to free
+/// \since AlignedDeallocate for SIMD since Crypto++ 1.0, AlignedAllocate
+///  for all builds since Crypto++ 8.1
+/// \sa AlignedAllocate, UnalignedAllocate, UnalignedDeallocate, CallNewHandler,
+///  <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
+CRYPTOPP_DLL void CRYPTOPP_API AlignedDeallocate(void *ptr);
+
+/// \brief Allocates a buffer
+/// \param size the size of the buffer
+/// \since Crypto++ 1.0
+/// \sa AlignedAllocate, AlignedDeallocate, UnalignedDeallocate, CallNewHandler,
+///  <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
+CRYPTOPP_DLL void * CRYPTOPP_API UnalignedAllocate(size_t size);
+
+/// \brief Frees a buffer allocated with UnalignedAllocate
+/// \param ptr the buffer to free
+/// \since Crypto++ 1.0
+/// \sa AlignedAllocate, AlignedDeallocate, UnalignedAllocate, CallNewHandler,
+///  <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
+CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *ptr);
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_ALLOCATE_H

+ 2 - 2
include/cryptlib/arc4.h

@@ -49,7 +49,7 @@ protected:
 /// \brief Alleged RC4
 /// \sa <a href="http://www.cryptopp.com/wiki/RC4">Alleged RC4</a>
 /// \since Crypto++ 3.1
-DOCUMENTED_TYPEDEF(SymmetricCipherFinal<ARC4_Base>, ARC4)
+DOCUMENTED_TYPEDEF(SymmetricCipherFinal<ARC4_Base>, ARC4);
 
 /// \brief MARC4 base class
 /// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions
@@ -70,7 +70,7 @@ protected:
 /// \brief Modified Alleged RC4
 /// \sa <a href="http://www.cryptopp.com/wiki/RC4">Alleged RC4</a>
 /// \since Crypto++ 3.1
-DOCUMENTED_TYPEDEF(SymmetricCipherFinal<MARC4_Base>, MARC4)
+DOCUMENTED_TYPEDEF(SymmetricCipherFinal<MARC4_Base>, MARC4);
 
 }
 #if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1

+ 1 - 1
include/cryptlib/aria.h

@@ -53,7 +53,7 @@ public:
 		typedef SecBlock<byte, AllocatorWithCleanup<byte, true> >     AlignedByteBlock;
 		typedef SecBlock<word32, AllocatorWithCleanup<word32, true> > AlignedWordBlock;
 
-		AlignedByteBlock  m_rk;  // round keys
+		AlignedWordBlock  m_rk;  // round keys
 		AlignedWordBlock  m_w;   // w0, w1, w2, w3, t and u
 		unsigned int m_rounds;
 	};

+ 427 - 0
include/cryptlib/arm_simd.h

@@ -0,0 +1,427 @@
+// arm_simd.h - written and placed in public domain by Jeffrey Walton
+
+/// \file arm_simd.h
+/// \brief Support functions for ARM and vector operations
+
+#ifndef CRYPTOPP_ARM_SIMD_H
+#define CRYPTOPP_ARM_SIMD_H
+
+#include "config.h"
+
+#if (CRYPTOPP_ARM_NEON_HEADER)
+# include <stdint.h>
+# include <arm_neon.h>
+#endif
+
+#if (CRYPTOPP_ARM_ACLE_HEADER)
+# include <stdint.h>
+# include <arm_acle.h>
+#endif
+
+#if (CRYPTOPP_ARM_CRC32_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+///	\name CRC32 checksum
+//@{
+
+/// \brief CRC32 checksum
+/// \param crc the starting crc value
+/// \param val the value to checksum
+/// \return CRC32 value
+/// \since Crypto++ 8.6
+inline uint32_t CRC32B (uint32_t crc, uint8_t val)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+	return __crc32b(crc, val);
+#else
+    __asm__ ("crc32b   %w0, %w0, %w1   \n\t"
+            :"+r" (crc) : "r" (val) );
+    return crc;
+#endif
+}
+
+/// \brief CRC32 checksum
+/// \param crc the starting crc value
+/// \param val the value to checksum
+/// \return CRC32 value
+/// \since Crypto++ 8.6
+inline uint32_t CRC32W (uint32_t crc, uint32_t val)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+	return __crc32w(crc, val);
+#else
+    __asm__ ("crc32w   %w0, %w0, %w1   \n\t"
+            :"+r" (crc) : "r" (val) );
+    return crc;
+#endif
+}
+
+/// \brief CRC32 checksum
+/// \param crc the starting crc value
+/// \param vals the values to checksum
+/// \return CRC32 value
+/// \since Crypto++ 8.6
+inline uint32_t CRC32Wx4 (uint32_t crc, const uint32_t vals[4])
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+	return __crc32w(__crc32w(__crc32w(__crc32w(
+             crc, vals[0]), vals[1]), vals[2]), vals[3]);
+#else
+    __asm__ ("crc32w   %w0, %w0, %w1   \n\t"
+             "crc32w   %w0, %w0, %w2   \n\t"
+             "crc32w   %w0, %w0, %w3   \n\t"
+             "crc32w   %w0, %w0, %w4   \n\t"
+            :"+r" (crc) : "r" (vals[0]), "r" (vals[1]),
+                          "r" (vals[2]), "r" (vals[3]));
+    return crc;
+#endif
+}
+
+//@}
+///	\name CRC32-C checksum
+
+/// \brief CRC32-C checksum
+/// \param crc the starting crc value
+/// \param val the value to checksum
+/// \return CRC32-C value
+/// \since Crypto++ 8.6
+inline uint32_t CRC32CB (uint32_t crc, uint8_t val)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+	return __crc32cb(crc, val);
+#else
+    __asm__ ("crc32cb   %w0, %w0, %w1   \n\t"
+            :"+r" (crc) : "r" (val) );
+    return crc;
+#endif
+}
+
+/// \brief CRC32-C checksum
+/// \param crc the starting crc value
+/// \param val the value to checksum
+/// \return CRC32-C value
+/// \since Crypto++ 8.6
+inline uint32_t CRC32CW (uint32_t crc, uint32_t val)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+	return __crc32cw(crc, val);
+#else
+    __asm__ ("crc32cw   %w0, %w0, %w1   \n\t"
+            :"+r" (crc) : "r" (val) );
+    return crc;
+#endif
+}
+
+/// \brief CRC32-C checksum
+/// \param crc the starting crc value
+/// \param vals the values to checksum
+/// \return CRC32-C value
+/// \since Crypto++ 8.6
+inline uint32_t CRC32CWx4 (uint32_t crc, const uint32_t vals[4])
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+	return __crc32cw(__crc32cw(__crc32cw(__crc32cw(
+             crc, vals[0]), vals[1]), vals[2]), vals[3]);
+#else
+    __asm__ ("crc32cw   %w0, %w0, %w1   \n\t"
+             "crc32cw   %w0, %w0, %w2   \n\t"
+             "crc32cw   %w0, %w0, %w3   \n\t"
+             "crc32cw   %w0, %w0, %w4   \n\t"
+            :"+r" (crc) : "r" (vals[0]), "r" (vals[1]),
+                          "r" (vals[2]), "r" (vals[3]));
+    return crc;
+#endif
+}
+//@}
+#endif  // CRYPTOPP_ARM_CRC32_AVAILABLE
+
+#if (CRYPTOPP_ARM_PMULL_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+///	\name Polynomial multiplication
+//@{
+
+/// \brief Polynomial multiplication
+/// \param a the first value
+/// \param b the second value
+/// \return vector product
+/// \details PMULL_00() performs polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x00)</tt>.
+///  The <tt>0x00</tt> indicates the low 64-bits of <tt>a</tt> and <tt>b</tt>
+///  are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and
+///  numbered 0.
+/// \since Crypto++ 8.0
+inline uint64x2_t PMULL_00(const uint64x2_t a, const uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    const __n64 x = { vgetq_lane_u64(a, 0) };
+    const __n64 y = { vgetq_lane_u64(b, 0) };
+    return vmull_p64(x, y);
+#elif defined(__GNUC__)
+    uint64x2_t r;
+    __asm__ ("pmull    %0.1q, %1.1d, %2.1d   \n\t"
+            :"=w" (r) : "w" (a), "w" (b) );
+    return r;
+#else
+    return (uint64x2_t)(vmull_p64(
+        vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
+        vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first value
+/// \param b the second value
+/// \return vector product
+/// \details PMULL_01 performs() polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x01)</tt>.
+///  The <tt>0x01</tt> indicates the low 64-bits of <tt>a</tt> and high
+///  64-bits of <tt>b</tt> are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and
+///  numbered 0.
+/// \since Crypto++ 8.0
+inline uint64x2_t PMULL_01(const uint64x2_t a, const uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    const __n64 x = { vgetq_lane_u64(a, 0) };
+    const __n64 y = { vgetq_lane_u64(b, 1) };
+    return vmull_p64(x, y);
+#elif defined(__GNUC__)
+    uint64x2_t r;
+    __asm__ ("pmull    %0.1q, %1.1d, %2.1d   \n\t"
+            :"=w" (r) : "w" (a), "w" (vget_high_u64(b)) );
+    return r;
+#else
+    return (uint64x2_t)(vmull_p64(
+        vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
+        vgetq_lane_u64(vreinterpretq_u64_u8(b),1)));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first value
+/// \param b the second value
+/// \return vector product
+/// \details PMULL_10() performs polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x10)</tt>.
+///  The <tt>0x10</tt> indicates the high 64-bits of <tt>a</tt> and low
+///  64-bits of <tt>b</tt> are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and
+///  numbered 0.
+/// \since Crypto++ 8.0
+inline uint64x2_t PMULL_10(const uint64x2_t a, const uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    const __n64 x = { vgetq_lane_u64(a, 1) };
+    const __n64 y = { vgetq_lane_u64(b, 0) };
+    return vmull_p64(x, y);
+#elif defined(__GNUC__)
+    uint64x2_t r;
+    __asm__ ("pmull    %0.1q, %1.1d, %2.1d   \n\t"
+            :"=w" (r) : "w" (vget_high_u64(a)), "w" (b) );
+    return r;
+#else
+    return (uint64x2_t)(vmull_p64(
+        vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
+        vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first value
+/// \param b the second value
+/// \return vector product
+/// \details PMULL_11() performs polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x11)</tt>.
+///  The <tt>0x11</tt> indicates the high 64-bits of <tt>a</tt> and <tt>b</tt>
+///  are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and
+///  numbered 0.
+/// \since Crypto++ 8.0
+inline uint64x2_t PMULL_11(const uint64x2_t a, const uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    const __n64 x = { vgetq_lane_u64(a, 1) };
+    const __n64 y = { vgetq_lane_u64(b, 1) };
+    return vmull_p64(x, y);
+#elif defined(__GNUC__)
+    uint64x2_t r;
+    __asm__ ("pmull2   %0.1q, %1.2d, %2.2d   \n\t"
+            :"=w" (r) : "w" (a), "w" (b) );
+    return r;
+#else
+    return (uint64x2_t)(vmull_p64(
+        vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
+        vgetq_lane_u64(vreinterpretq_u64_u8(b),1)));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first value
+/// \param b the second value
+/// \return vector product
+/// \details PMULL() performs vmull_p64(). PMULL is provided as
+///  GCC inline assembly due to Clang and lack of support for the intrinsic.
+/// \since Crypto++ 8.0
+inline uint64x2_t PMULL(const uint64x2_t a, const uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    const __n64 x = { vgetq_lane_u64(a, 0) };
+    const __n64 y = { vgetq_lane_u64(b, 0) };
+    return vmull_p64(x, y);
+#elif defined(__GNUC__)
+    uint64x2_t r;
+    __asm__ ("pmull    %0.1q, %1.1d, %2.1d   \n\t"
+            :"=w" (r) : "w" (a), "w" (b) );
+    return r;
+#else
+    return (uint64x2_t)(vmull_p64(
+        vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
+        vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first value
+/// \param b the second value
+/// \return vector product
+/// \details PMULL_HIGH() performs vmull_high_p64(). PMULL_HIGH is provided as
+///  GCC inline assembly due to Clang and lack of support for the intrinsic.
+/// \since Crypto++ 8.0
+inline uint64x2_t PMULL_HIGH(const uint64x2_t a, const uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    const __n64 x = { vgetq_lane_u64(a, 1) };
+    const __n64 y = { vgetq_lane_u64(b, 1) };
+    return vmull_p64(x, y);
+#elif defined(__GNUC__)
+    uint64x2_t r;
+    __asm__ ("pmull2   %0.1q, %1.2d, %2.2d   \n\t"
+            :"=w" (r) : "w" (a), "w" (b) );
+    return r;
+#else
+    return (uint64x2_t)(vmull_p64(
+        vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
+        vgetq_lane_u64(vreinterpretq_u64_u8(b),1))));
+#endif
+}
+
+/// \brief Vector extraction
+/// \tparam C the byte count
+/// \param a the first value
+/// \param b the second value
+/// \return vector
+/// \details VEXT_U8() extracts the first <tt>C</tt> bytes of vector
+///  <tt>a</tt> and the remaining bytes in <tt>b</tt>. VEXT_U8 is provided
+///  as GCC inline assembly due to Clang and lack of support for the intrinsic.
+/// \since Crypto++ 8.0
+template <unsigned int C>
+inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b)
+{
+    // https://github.com/weidai11/cryptopp/issues/366
+#if defined(CRYPTOPP_MSC_VERSION)
+    return vreinterpretq_u64_u8(vextq_u8(
+        vreinterpretq_u8_u64(a), vreinterpretq_u8_u64(b), C));
+#else
+    uint64x2_t r;
+    __asm__ ("ext   %0.16b, %1.16b, %2.16b, %3   \n\t"
+            :"=w" (r) : "w" (a), "w" (b), "I" (C) );
+    return r;
+#endif
+}
+
+//@}
+#endif // CRYPTOPP_ARM_PMULL_AVAILABLE
+
+#if CRYPTOPP_ARM_SHA3_AVAILABLE  || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+///	\name ARMv8.2 operations
+//@{
+
+/// \brief Three-way XOR
+/// \param a the first value
+/// \param b the second value
+/// \param c the third value
+/// \return three-way exclusive OR of the values
+/// \details VEOR3() performs veor3q_u64(). VEOR3 is provided as GCC inline assembly due
+///  to Clang and lack of support for the intrinsic.
+/// \details VEOR3 requires ARMv8.2.
+/// \since Crypto++ 8.6
+inline uint64x2_t VEOR3(uint64x2_t a, uint64x2_t b, uint64x2_t c)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    return veor3q_u64(a, b, c);
+#else
+    uint64x2_t r;
+    __asm__ ("eor3   %0.16b, %1.16b, %2.16b, %3.16b   \n\t"
+            :"=w" (r) : "w" (a), "w" (b), "w" (c));
+    return r;
+#endif
+}
+
+/// \brief XOR and rotate
+/// \param a the first value
+/// \param b the second value
+/// \param c the third value
+/// \return two-way exclusive OR of the values, then rotated by c
+/// \details VXARQ() performs vxarq_u64(). VXARQ is provided as GCC inline assembly due
+///  to Clang and lack of support for the intrinsic.
+/// \details VXARQ requires ARMv8.2.
+/// \since Crypto++ 8.6
+inline uint64x2_t VXAR(uint64x2_t a, uint64x2_t b, const int c)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    return vxarq_u64(a, b, c);
+#else
+    uint64x2_t r;
+    __asm__ ("xar   %0.2d, %1.2d, %2.2d, %3   \n\t"
+            :"=w" (r) : "w" (a), "w" (b), "I" (c));
+    return r;
+#endif
+}
+
+/// \brief XOR and rotate
+/// \tparam C the rotate amount
+/// \param a the first value
+/// \param b the second value
+/// \return two-way exclusive OR of the values, then rotated by C
+/// \details VXARQ() performs vxarq_u64(). VXARQ is provided as GCC inline assembly due
+///  to Clang and lack of support for the intrinsic.
+/// \details VXARQ requires ARMv8.2.
+/// \since Crypto++ 8.6
+template <unsigned int C>
+inline uint64x2_t VXAR(uint64x2_t a, uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    return vxarq_u64(a, b, C);
+#else
+    uint64x2_t r;
+    __asm__ ("xar   %0.2d, %1.2d, %2.2d, %3   \n\t"
+            :"=w" (r) : "w" (a), "w" (b), "I" (C));
+    return r;
+#endif
+}
+
+/// \brief XOR and rotate
+/// \param a the first value
+/// \param b the second value
+/// \return two-way exclusive OR of the values, then rotated 1-bit
+/// \details VRAX1() performs vrax1q_u64(). VRAX1 is provided as GCC inline assembly due
+///  to Clang and lack of support for the intrinsic.
+/// \details VRAX1 requires ARMv8.2.
+/// \since Crypto++ 8.6
+inline uint64x2_t VRAX1(uint64x2_t a, uint64x2_t b)
+{
+#if defined(CRYPTOPP_MSC_VERSION)
+    return vrax1q_u64(a, b);
+#else
+    uint64x2_t r;
+    __asm__ ("rax1   %0.2d, %1.2d, %2.2d   \n\t"
+            :"=w" (r) : "w" (a), "w" (b));
+    return r;
+#endif
+}
+//@}
+#endif  // CRYPTOPP_ARM_SHA3_AVAILABLE
+
+#endif // CRYPTOPP_ARM_SIMD_H

+ 445 - 57
include/cryptlib/asn.h

@@ -13,6 +13,8 @@
 #include "queue.h"
 #include "misc.h"
 
+#include <iosfwd>
+
 // Issue 340
 #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
 # pragma GCC diagnostic push
@@ -23,45 +25,78 @@
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief ASN.1 types
-/// \note These tags and flags are not complete
+/// \note These tags are not complete
 enum ASNTag
 {
+	/// \brief ASN.1 Boolean
 	BOOLEAN 			= 0x01,
+	/// \brief ASN.1 Integer
 	INTEGER 			= 0x02,
+	/// \brief ASN.1 Bit string
 	BIT_STRING			= 0x03,
+	/// \brief ASN.1 Octet string
 	OCTET_STRING		= 0x04,
+	/// \brief ASN.1 Null
 	TAG_NULL			= 0x05,
+	/// \brief ASN.1 Object identifier
 	OBJECT_IDENTIFIER	= 0x06,
+	/// \brief ASN.1 Object descriptor
 	OBJECT_DESCRIPTOR	= 0x07,
+	/// \brief ASN.1 External reference
 	EXTERNAL			= 0x08,
+	/// \brief ASN.1 Real integer
 	REAL				= 0x09,
+	/// \brief ASN.1 Enumerated value
 	ENUMERATED			= 0x0a,
+	/// \brief ASN.1 UTF-8 string
 	UTF8_STRING			= 0x0c,
+	/// \brief ASN.1 Sequence
 	SEQUENCE			= 0x10,
+	/// \brief ASN.1 Set
 	SET 				= 0x11,
+	/// \brief ASN.1 Numeric string
 	NUMERIC_STRING		= 0x12,
+	/// \brief ASN.1 Printable string
 	PRINTABLE_STRING 	= 0x13,
+	/// \brief ASN.1 T61 string
 	T61_STRING			= 0x14,
+	/// \brief ASN.1 Videotext string
 	VIDEOTEXT_STRING 	= 0x15,
+	/// \brief ASN.1 IA5 string
 	IA5_STRING			= 0x16,
+	/// \brief ASN.1 UTC time
 	UTC_TIME 			= 0x17,
+	/// \brief ASN.1 Generalized time
 	GENERALIZED_TIME 	= 0x18,
+	/// \brief ASN.1 Graphic string
 	GRAPHIC_STRING		= 0x19,
+	/// \brief ASN.1 Visible string
 	VISIBLE_STRING		= 0x1a,
-	GENERAL_STRING		= 0x1b
+	/// \brief ASN.1 General string
+	GENERAL_STRING		= 0x1b,
+	/// \brief ASN.1 Universal string
+	UNIVERSAL_STRING	= 0x1c,
+	/// \brief ASN.1 BMP string
+	BMP_STRING  		= 0x1e
 };
 
 /// \brief ASN.1 flags
-/// \note These tags and flags are not complete
+/// \note These flags are not complete
 enum ASNIdFlag
 {
+	/// \brief ASN.1 Universal class
 	UNIVERSAL           = 0x00,
-//	DATA                = 0x01,
-//	HEADER              = 0x02,
+	// DATA           = 0x01,
+	// HEADER           = 0x02,
+	/// \brief ASN.1 Primitive flag
 	PRIMITIVE           = 0x00,
+	/// \brief ASN.1 Constructed flag
 	CONSTRUCTED         = 0x20,
+	/// \brief ASN.1 Application class
 	APPLICATION         = 0x40,
+	/// \brief ASN.1 Context specific class
 	CONTEXT_SPECIFIC    = 0x80,
+	/// \brief ASN.1 Private class
 	PRIVATE             = 0xc0
 };
 
@@ -75,23 +110,21 @@ public:
 	/// \brief Construct an UnknownOID
 	UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
 	/// \brief Construct an UnknownOID
-	/// \param err error message to use for the execption
+	/// \param err error message to use for the exception
 	UnknownOID(const char *err) : BERDecodeErr(err) {}
 };
 
-// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
-
 /// \brief DER encode a length
 /// \param bt BufferedTransformation object for writing
 /// \param length the size to encode
-/// \returns the number of octets used for the encoding
+/// \return the number of octets used for the encoding
 CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &bt, lword length);
 
 /// \brief BER decode a length
 /// \param bt BufferedTransformation object for reading
 /// \param length the decoded size
-/// \returns true if the value was decoded
-/// \throws BERDecodeError if the value fails to decode or is too large for size_t
+/// \return true if the value was decoded
+/// \throw BERDecodeError if the value fails to decode or is too large for size_t
 /// \details BERLengthDecode() returns false if the encoding is indefinite length.
 CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &bt, size_t &length);
 
@@ -107,54 +140,110 @@ CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &bt);
 /// \param bt BufferedTransformation object for writing
 /// \param str the string to encode
 /// \param strLen the length of the string
-/// \returns the number of octets used for the encoding
+/// \return the number of octets used for the encoding
 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen);
 
 /// \brief DER encode octet string
 /// \param bt BufferedTransformation object for reading
 /// \param str the string to encode
-/// \returns the number of octets used for the encoding
+/// \return the number of octets used for the encoding
 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str);
 
 /// \brief BER decode octet string
 /// \param bt BufferedTransformation object for reading
 /// \param str the decoded string
-/// \returns the number of octets used for the encoding
+/// \return the number of octets used for the encoding
 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str);
 
 /// \brief BER decode octet string
 /// \param bt BufferedTransformation object for reading
 /// \param str the decoded string
-/// \returns the number of octets used for the encoding
+/// \return the number of octets used for the encoding
 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str);
 
 /// \brief DER encode text string
 /// \param bt BufferedTransformation object for writing
 /// \param str the string to encode
-/// \param asnTag the ASN.1 type
-/// \returns the number of octets used for the encoding
+/// \param strLen the length of the string, in bytes
+/// \param asnTag the ASN.1 identifier
+/// \return the number of octets used for the encoding
+/// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+/// \since Crypto++ 8.3
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const byte* str, size_t strLen, byte asnTag);
+
+/// \brief DER encode text string
+/// \param bt BufferedTransformation object for writing
+/// \param str the string to encode
+/// \param asnTag the ASN.1 identifier
+/// \return the number of octets used for the encoding
 /// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+/// \since Crypto++ 8.3
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag);
+
+/// \brief DER encode text string
+/// \param bt BufferedTransformation object for writing
+/// \param str the string to encode
+/// \param asnTag the ASN.1 identifier
+/// \return the number of octets used for the encoding
+/// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+/// \since Crypto++ 6.0
 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag);
 
 /// \brief BER decode text string
 /// \param bt BufferedTransformation object for reading
-/// \param str the string to encode
-/// \param asnTag the ASN.1 type
-/// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+/// \param str the string to decode
+/// \param asnTag the ASN.1 identifier
+/// \details BERDecodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+/// \since Crypto++ 8.3
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &bt, SecByteBlock &str, byte asnTag);
+
+/// \brief BER decode text string
+/// \param bt BufferedTransformation object for reading
+/// \param str the string to decode
+/// \param asnTag the ASN.1 identifier
+/// \details BERDecodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+/// \since Crypto++ 6.0
 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag);
 
+/// \brief DER encode date
+/// \param bt BufferedTransformation object for writing
+/// \param str the date to encode
+/// \param asnTag the ASN.1 identifier
+/// \return the number of octets used for the encoding
+/// \details BERDecodeDate() can be used for UTC_TIME and GENERALIZED_TIME
+/// \since Crypto++ 8.3
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeDate(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag);
+
+/// \brief BER decode date
+/// \param bt BufferedTransformation object for reading
+/// \param str the date to decode
+/// \param asnTag the ASN.1 identifier
+/// \details BERDecodeDate() can be used for UTC_TIME and GENERALIZED_TIME
+/// \since Crypto++ 8.3
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeDate(BufferedTransformation &bt, SecByteBlock &str, byte asnTag);
+
 /// \brief DER encode bit string
 /// \param bt BufferedTransformation object for writing
 /// \param str the string to encode
 /// \param strLen the length of the string
 /// \param unusedBits the number of unused bits
-/// \returns the number of octets used for the encoding
+/// \return the number of octets used for the encoding
+/// \details The caller is responsible for shifting octets if unusedBits is
+///  not 0. For example, to DER encode a web server X.509 key usage, the 101b
+///  bit mask is often used (digitalSignature and keyEncipherment). In this
+///  case <tt>str</tt> is one octet with a value=0xa0 and unusedBits=5. The
+///  value 0xa0 is <tt>101b << 5</tt>.
 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits=0);
 
 /// \brief DER decode bit string
 /// \param bt BufferedTransformation object for reading
 /// \param str the decoded string
 /// \param unusedBits the number of unused bits
+/// \details The caller is responsible for shifting octets if unusedBits is
+///  not 0. For example, to DER encode a web server X.509 key usage, the 101b
+///  bit mask is often used (digitalSignature and keyEncipherment). In this
+///  case <tt>str</tt> is one octet with a value=0xa0 and unusedBits=5. The
+///  value 0xa0 is <tt>101b << 5</tt>.
 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits);
 
 /// \brief BER decode and DER re-encode
@@ -162,6 +251,15 @@ CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &bt,
 /// \param dest BufferedTransformation object
 CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &bt, BufferedTransformation &dest);
 
+/// \brief BER decode size
+/// \param bt BufferedTransformation object for reading
+/// \return the length of the ASN.1 value, in bytes
+/// \details BERDecodePeekLength() determines the length of a value without
+///  consuming octets in the stream. The stream must use definite length encoding.
+///  If indefinite length encoding is used or an error occurs, then 0 is returned.
+/// \since Crypto++ 8.3
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodePeekLength(const BufferedTransformation &bt);
+
 /// \brief Object Identifier
 class CRYPTOPP_DLL OID
 {
@@ -170,16 +268,22 @@ public:
 
 	/// \brief Construct an OID
 	OID() {}
+
 	/// \brief Construct an OID
 	/// \param v value to initialize the OID
 	OID(word32 v) : m_values(1, v) {}
+
 	/// \brief Construct an OID
 	/// \param bt BufferedTransformation object
-	OID(BufferedTransformation &bt) {BERDecode(bt);}
+	OID(BufferedTransformation &bt) {
+		BERDecode(bt);
+	}
 
 	/// \brief Append a value to an OID
 	/// \param rhs the value to append
-	inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
+	inline OID & operator+=(word32 rhs) {
+		m_values.push_back(rhs); return *this;
+	}
 
 	/// \brief DER encode this OID
 	/// \param bt BufferedTransformation object
@@ -191,7 +295,7 @@ public:
 
 	/// \brief BER decode an OID
 	/// \param bt BufferedTransformation object
-	/// \throws BERDecodeErr() if decoded value doesn't match an expected OID
+	/// \throw BERDecodeErr() if decoded value doesn't match an expected OID
 	/// \details BERDecodeAndCheck() can be used to parse an OID and verify it matches an expected.
 	/// <pre>
 	///   BERSequenceDecoder key(bt);
@@ -201,14 +305,35 @@ public:
 	/// </pre>
 	void BERDecodeAndCheck(BufferedTransformation &bt) const;
 
+	/// \brief Determine if OID is empty
+	/// \return true if OID has 0 elements, false otherwise
+	/// \since Crypto++ 8.0
+	bool Empty() const {
+		return m_values.empty();
+	}
+
+	/// \brief Retrieve OID value array
+	/// \return OID value vector
+	/// \since Crypto++ 8.0
 	const std::vector<word32>& GetValues() const {
 		return m_values;
 	}
 
+	/// \brief Print an OID
+	/// \param out ostream object
+	/// \return ostream reference
+	/// \details Print() writes the OID in a customary format, like
+	///  1.2.840.113549.1.1.11. The caller is reposnsible to convert the
+	///  OID to a friendly name, like sha256WithRSAEncryption.
+	/// \since Crypto++ 8.3
+	std::ostream& Print(std::ostream& out) const;
+
 protected:
 	friend bool operator==(const OID &lhs, const OID &rhs);
 	friend bool operator!=(const OID &lhs, const OID &rhs);
 	friend bool operator<(const OID &lhs, const OID &rhs);
+	friend bool operator<=(const OID &lhs, const OID &rhs);
+	friend bool operator>=(const OID &lhs, const OID &rhs);
 
 	std::vector<word32> m_values;
 
@@ -254,21 +379,99 @@ private:
 class CRYPTOPP_DLL BERGeneralDecoder : public Store
 {
 public:
+	/// \brief Default ASN.1 tag
+	enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
+
 	virtual ~BERGeneralDecoder();
 
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \details BERGeneralDecoder uses DefaultTag
+	explicit BERGeneralDecoder(BufferedTransformation &inQueue);
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \param asnTag ASN.1 tag
 	explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \param asnTag ASN.1 tag
 	explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
 
-	bool IsDefiniteLength() const {return m_definiteLength;}
-	lword RemainingLength() const {CRYPTOPP_ASSERT(m_definiteLength); return m_length;}
+	/// \brief Determine length encoding
+	/// \return true if the ASN.1 object is definite length encoded, false otherwise
+	bool IsDefiniteLength() const {
+		return m_definiteLength;
+	}
+
+	/// \brief Determine remaining length
+	/// \return number of octets that remain to be consumed
+	/// \details RemainingLength() is only valid if IsDefiniteLength()
+	///  returns true.
+	lword RemainingLength() const {
+		CRYPTOPP_ASSERT(m_definiteLength);
+		return IsDefiniteLength() ? m_length : 0;
+	}
+
+	/// \brief Determine end of stream
+	/// \return true if all octets have been consumed, false otherwise
 	bool EndReached() const;
+
+	/// \brief Determine next octet
+	/// \return next octet in the stream
+	/// \details PeekByte does not consume the octet.
+	/// \throw BERDecodeError if there are no octets remaining
 	byte PeekByte() const;
+
+	/// \brief Determine next octet
+	/// \details CheckByte reads the next byte in the stream and verifies
+	///  the octet matches b.
+	/// \throw BERDecodeError if the next octet is not b
 	void CheckByte(byte b);
 
+	/// \brief Transfer bytes to another BufferedTransformation
+	/// \param target the destination BufferedTransformation
+	/// \param transferBytes the number of bytes to transfer
+	/// \param channel the channel on which the transfer should occur
+	/// \param blocking specifies whether the object should block when
+	///  processing input
+	/// \return the number of bytes that remain in the transfer block
+	///  (i.e., bytes not transferred)
+	/// \details TransferTo2() removes bytes and moves
+	///  them to the destination. Transfer begins at the index position
+	///  in the current stream, and not from an absolute position in the
+	///  stream.
+	/// \details transferBytes is an \a IN and \a OUT parameter. When
+	///  the call is made, transferBytes is the requested size of the
+	///  transfer. When the call returns, transferBytes is the number
+	///  of bytes that were transferred.
 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+
+	/// \brief Copy bytes to another BufferedTransformation
+	/// \param target the destination BufferedTransformation
+	/// \param begin the 0-based index of the first byte to copy in
+	///  the stream
+	/// \param end the 0-based index of the last byte to copy in
+	///  the stream
+	/// \param channel the channel on which the transfer should occur
+	/// \param blocking specifies whether the object should block when
+	///  processing input
+	/// \return the number of bytes that remain in the copy block
+	///  (i.e., bytes not copied)
+	/// \details CopyRangeTo2 copies bytes to the
+	///  destination. The bytes are not removed from this object. Copying
+	///  begins at the index position in the current stream, and not from
+	///  an absolute position in the stream.
+	/// \details begin is an \a IN and \a OUT parameter. When the call is
+	///  made, begin is the starting position of the copy. When the call
+	///  returns, begin is the position of the first byte that was \a not
+	///  copied (which may be different than end). begin can be used for
+	///  subsequent calls to CopyRangeTo2().
 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
 
-	// call this to denote end of sequence
+	/// \brief Signals the end of messages to the object
+	/// \details Call this to denote end of sequence
 	void MessageEnd();
 
 protected:
@@ -287,12 +490,28 @@ private:
 class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
 {
 public:
+	/// \brief Default ASN.1 tag
+	enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
+
 	virtual ~DERGeneralEncoder();
 
-	explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
-	explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \details DERGeneralEncoder uses DefaultTag
+	explicit DERGeneralEncoder(BufferedTransformation &outQueue);
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \param asnTag ASN.1 tag
+	explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag);
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \param asnTag ASN.1 tag
+	explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag);
 
-	// call this to denote end of sequence
+	/// \brief Signals the end of messages to the object
+	/// \details Call this to denote end of sequence
 	void MessageEnd();
 
 private:
@@ -305,9 +524,31 @@ private:
 class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
 {
 public:
-	explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+	/// \brief Default ASN.1 tag
+	enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \details BERSequenceDecoder uses DefaultTag
+	explicit BERSequenceDecoder(BufferedTransformation &inQueue)
+		: BERGeneralDecoder(inQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \param asnTag ASN.1 tag
+	explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag)
 		: BERGeneralDecoder(inQueue, asnTag) {}
-	explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \details BERSequenceDecoder uses DefaultTag
+	explicit BERSequenceDecoder(BERSequenceDecoder &inQueue)
+		: BERGeneralDecoder(inQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \param asnTag ASN.1 tag
+	explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag)
 		: BERGeneralDecoder(inQueue, asnTag) {}
 };
 
@@ -315,9 +556,31 @@ public:
 class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
 {
 public:
-	explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+	/// \brief Default ASN.1 tag
+	enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \details DERSequenceEncoder uses DefaultTag
+	explicit DERSequenceEncoder(BufferedTransformation &outQueue)
+		: DERGeneralEncoder(outQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \param asnTag ASN.1 tag
+	explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag)
 		: DERGeneralEncoder(outQueue, asnTag) {}
-	explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \details DERSequenceEncoder uses DefaultTag
+	explicit DERSequenceEncoder(DERSequenceEncoder &outQueue)
+		: DERGeneralEncoder(outQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \param asnTag ASN.1 tag
+	explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag)
 		: DERGeneralEncoder(outQueue, asnTag) {}
 };
 
@@ -325,9 +588,31 @@ public:
 class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
 {
 public:
-	explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
+	/// \brief Default ASN.1 tag
+	enum {DefaultTag = SET | EnumToInt(CONSTRUCTED)};
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \details BERSetDecoder uses DefaultTag
+	explicit BERSetDecoder(BufferedTransformation &inQueue)
+		: BERGeneralDecoder(inQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \param asnTag ASN.1 tag
+	explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag)
 		: BERGeneralDecoder(inQueue, asnTag) {}
-	explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \details BERSetDecoder uses DefaultTag
+	explicit BERSetDecoder(BERSetDecoder &inQueue)
+		: BERGeneralDecoder(inQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 decoder
+	/// \param inQueue input byte queue
+	/// \param asnTag ASN.1 tag
+	explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag)
 		: BERGeneralDecoder(inQueue, asnTag) {}
 };
 
@@ -335,9 +620,31 @@ public:
 class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
 {
 public:
-	explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
+	/// \brief Default ASN.1 tag
+	enum {DefaultTag = SET | EnumToInt(CONSTRUCTED)};
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \details DERSetEncoder uses DefaultTag
+	explicit DERSetEncoder(BufferedTransformation &outQueue)
+		: DERGeneralEncoder(outQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \param asnTag ASN.1 tag
+	explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag)
 		: DERGeneralEncoder(outQueue, asnTag) {}
-	explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \details DERSetEncoder uses DefaultTag
+	explicit DERSetEncoder(DERSetEncoder &outQueue)
+		: DERGeneralEncoder(outQueue, DefaultTag) {}
+
+	/// \brief Construct an ASN.1 encoder
+	/// \param outQueue output byte queue
+	/// \param asnTag ASN.1 tag
+	explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag)
 		: DERGeneralEncoder(outQueue, asnTag) {}
 };
 
@@ -380,7 +687,7 @@ public:
 	/// \param bt BufferedTransformation object
 	/// \details Save() will write the OID associated with algorithm or scheme.
 	///   In the case of public and private keys, this function writes the
-	///   subjectPubicKeyInfo and privateKeyInfo parts.
+	///   subjectPublicKeyInfo and privateKeyInfo parts.
 	void Save(BufferedTransformation &bt) const
 		{BEREncode(bt);}
 
@@ -400,20 +707,43 @@ public:
 	void DEREncode(BufferedTransformation &bt) const;
 
 	/// \brief Retrieves the OID of the algorithm
-	/// \returns OID of the algorithm
+	/// \return OID of the algorithm
 	virtual OID GetAlgorithmID() const =0;
+
+	/// \brief Decode algorithm parameters
+	/// \param bt BufferedTransformation object
+	/// \sa BERDecodePublicKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
+	///  2459, section 7.3.1</A>
 	virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
 		{BERDecodeNull(bt); return false;}
+
+	/// \brief Encode algorithm parameters
+	/// \param bt BufferedTransformation object
+	/// \sa DEREncodePublicKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
+	///  2459, section 7.3.1</A>
 	virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
-		{DEREncodeNull(bt); return false;}	// see RFC 2459, section 7.3.1
+		{DEREncodeNull(bt); return false;}
 
-	/// decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
+	/// \brief Decode subjectPublicKey part of subjectPublicKeyInfo
+	/// \param bt BufferedTransformation object
+	/// \param parametersPresent flag indicating if algorithm parameters are present
+	/// \param size number of octets to read for the parameters, in bytes
+	/// \details BERDecodePublicKey() the decodes subjectPublicKey part of
+	///  subjectPublicKeyInfo, without the BIT STRING header.
+	/// \details When <tt>parametersPresent = true</tt> then BERDecodePublicKey() calls
+	///  BERDecodeAlgorithmParameters() to parse algorithm parameters.
+	/// \sa BERDecodeAlgorithmParameters
 	virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
-	/// encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
+
+	/// \brief Encode subjectPublicKey part of subjectPublicKeyInfo
+	/// \param bt BufferedTransformation object
+	/// \details DEREncodePublicKey() encodes the subjectPublicKey part of
+	///  subjectPublicKeyInfo, without the BIT STRING header.
+	/// \sa DEREncodeAlgorithmParameters
 	virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
 };
 
-/// \brief Encodes and decodesprivateKeyInfo
+/// \brief Encodes and Decodes privateKeyInfo
 class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
 {
 public:
@@ -423,22 +753,55 @@ public:
 	void DEREncode(BufferedTransformation &bt) const;
 
 	/// \brief Retrieves the OID of the algorithm
-	/// \returns OID of the algorithm
+	/// \return OID of the algorithm
 	virtual OID GetAlgorithmID() const =0;
+
+	/// \brief Decode optional parameters
+	/// \param bt BufferedTransformation object
+	/// \sa BERDecodePrivateKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
+	///  2459, section 7.3.1</A>
 	virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
 		{BERDecodeNull(bt); return false;}
+
+	/// \brief Encode optional parameters
+	/// \param bt BufferedTransformation object
+	/// \sa DEREncodePrivateKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
+	///  2459, section 7.3.1</A>
 	virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
-		{DEREncodeNull(bt); return false;}	// see RFC 2459, section 7.3.1
+		{DEREncodeNull(bt); return false;}
 
-	/// decode privateKey part of privateKeyInfo, without the OCTET STRING header
+	/// \brief Decode privateKey part of privateKeyInfo
+	/// \param bt BufferedTransformation object
+	/// \param parametersPresent flag indicating if algorithm parameters are present
+	/// \param size number of octets to read for the parameters, in bytes
+	/// \details BERDecodePrivateKey() the decodes privateKey part of privateKeyInfo,
+	///  without the OCTET STRING header.
+	/// \details When <tt>parametersPresent = true</tt> then BERDecodePrivateKey() calls
+	///  BERDecodeAlgorithmParameters() to parse algorithm parameters.
+	/// \sa BERDecodeAlgorithmParameters
 	virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
-	/// encode privateKey part of privateKeyInfo, without the OCTET STRING header
+
+	/// \brief Encode privateKey part of privateKeyInfo
+	/// \param bt BufferedTransformation object
+	/// \details DEREncodePrivateKey() encodes the privateKey part of privateKeyInfo,
+	///  without the OCTET STRING header.
+	/// \sa DEREncodeAlgorithmParameters
 	virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
 
-	/// decode optional attributes including context-specific tag
-	/*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
+	/// \brief Decode optional attributes
+	/// \param bt BufferedTransformation object
+	/// \details BERDecodeOptionalAttributes() decodes optional attributes including
+	///  context-specific tag.
+	/// \sa BERDecodeAlgorithmParameters, DEREncodeOptionalAttributes
+	/// \note default implementation stores attributes to be output using
+	///  DEREncodeOptionalAttributes
 	virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
-	/// encode optional attributes including context-specific tag
+
+	/// \brief Encode optional attributes
+	/// \param bt BufferedTransformation object
+	/// \details DEREncodeOptionalAttributes() encodes optional attributes including
+	///  context-specific tag.
+	/// \sa BERDecodeAlgorithmParameters
 	virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
 
 protected:
@@ -451,7 +814,7 @@ protected:
 /// \tparam T class or type
 /// \param out BufferedTransformation object
 /// \param w unsigned value to encode
-/// \param asnTag the ASN.1 type
+/// \param asnTag the ASN.1 identifier
 /// \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
 template <class T>
 size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
@@ -484,10 +847,10 @@ size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER
 /// \tparam T fundamental C++ type
 /// \param in BufferedTransformation object
 /// \param w the decoded value
-/// \param asnTag the ASN.1 type
+/// \param asnTag the ASN.1 identifier
 /// \param minValue the minimum expected value
 /// \param maxValue the maximum expected value
-/// \throws BERDecodeErr() if the value cannot be parsed or the decoded value is not within range.
+/// \throw BERDecodeErr() if the value cannot be parsed or the decoded value is not within range.
 /// \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
 template <class T>
 void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
@@ -539,23 +902,42 @@ void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
 /// \brief Compare two OIDs for equality
 /// \param lhs the first OID
 /// \param rhs the second OID
-/// \returns true if the OIDs are equal, false otherwise
+/// \return true if the OIDs are equal, false otherwise
 inline bool operator==(const OID &lhs, const OID &rhs);
 /// \brief Compare two OIDs for inequality
 /// \param lhs the first OID
 /// \param rhs the second OID
-/// \returns true if the OIDs are not equal, false otherwise
+/// \return true if the OIDs are not equal, false otherwise
 inline bool operator!=(const OID &lhs, const OID &rhs);
 /// \brief Compare two OIDs for ordering
 /// \param lhs the first OID
 /// \param rhs the second OID
-/// \returns true if the first OID is less than the second OID, false otherwise
+/// \return true if the first OID is less than the second OID, false otherwise
 /// \details operator<() calls std::lexicographical_compare() on each element in the array of values.
 inline bool operator<(const OID &lhs, const OID &rhs);
+/// \brief Compare two OIDs for ordering
+/// \param lhs the first OID
+/// \param rhs the second OID
+/// \return true if the first OID is less than or equal to the second OID, false otherwise
+/// \details operator<=() is implemented in terms of operator==() and operator<().
+/// \since Crypto++ 8.3
+inline bool operator<=(const OID &lhs, const OID &rhs);
+/// \brief Compare two OIDs for ordering
+/// \param lhs the first OID
+/// \param rhs the second OID
+/// \return true if the first OID is greater than or equal to the second OID, false otherwise
+/// \details operator>=() is implemented in terms of operator<().
+/// \since Crypto++ 8.3
+inline bool operator>=(const OID &lhs, const OID &rhs);
 /// \brief Append a value to an OID
 /// \param lhs the OID
 /// \param rhs the value to append
 inline OID operator+(const OID &lhs, unsigned long rhs);
+/// \brief Print a OID value
+/// \param out the output stream
+/// \param oid the OID
+inline std::ostream& operator<<(std::ostream& out, const OID &oid)
+	{ return oid.Print(out); }
 #else
 inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
 	{return lhs.m_values == rhs.m_values;}
@@ -563,8 +945,14 @@ inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
 	{return lhs.m_values != rhs.m_values;}
 inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
 	{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
+inline bool operator<=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
+	{return lhs<rhs || lhs==rhs;}
+inline bool operator>=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
+	{return ! (lhs<rhs);}
 inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
 	{return ::CryptoPP::OID(lhs)+=rhs;}
+inline std::ostream& operator<<(std::ostream& out, const OID &oid)
+	{ return oid.Print(out); }
 #endif
 
 NAMESPACE_END

+ 1 - 1
include/cryptlib/authenc.h

@@ -60,7 +60,7 @@ protected:
 
 	void AuthenticateData(const byte *data, size_t len);
 	const SymmetricCipher & GetSymmetricCipher() const
-		{return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
+		{return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();}
 
 	virtual SymmetricCipher & AccessSymmetricCipher() =0;
 	virtual bool AuthenticationIsOnPlaintext() const =0;

+ 19 - 12
include/cryptlib/basecode.h

@@ -30,16 +30,18 @@ public:
 	/// \param attachment a BufferedTransformation to attach to this object
 	/// \param padding the character to use as padding
 	/// \pre log2base must be between 1 and 7 inclusive
-	/// \throws InvalidArgument if log2base is not between 1 and 7
+	/// \throw InvalidArgument if log2base is not between 1 and 7
 	BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULLPTR, int padding=-1)
 		: m_alphabet(NULLPTR), m_padding(0), m_bitsPerChar(0)
 		, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
 	{
 		Detach(attachment);
-		IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet)
-			(Name::Log2Base(), log2base)
-			(Name::Pad(), padding != -1)
-			(Name::PaddingByte(), byte(padding)));
+		BaseN_Encoder::IsolatedInitialize(
+			MakeParameters
+				(Name::EncodingLookupArray(), alphabet)
+				(Name::Log2Base(), log2base)
+				(Name::Pad(), padding != -1)
+				(Name::PaddingByte(), byte(padding)));
 	}
 
 	void IsolatedInitialize(const NameValuePairs &parameters);
@@ -61,7 +63,7 @@ public:
 	/// \details padding is set to -1, which means use default padding. If not
 	///   required, then the value must be set via IsolatedInitialize().
 	BaseN_Decoder(BufferedTransformation *attachment=NULLPTR)
-		: m_lookup(NULLPTR), m_padding(0), m_bitsPerChar(0)
+		: m_lookup(NULLPTR), m_bitsPerChar(0)
 		, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
 			{Detach(attachment);}
 
@@ -74,11 +76,14 @@ public:
 	/// \details padding is set to -1, which means use default padding. If not
 	///   required, then the value must be set via IsolatedInitialize().
 	BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULLPTR)
-		: m_lookup(NULLPTR), m_padding(0), m_bitsPerChar(0)
+		: m_lookup(NULLPTR), m_bitsPerChar(0)
 		, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
 	{
 		Detach(attachment);
-		IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base));
+		BaseN_Decoder::IsolatedInitialize(
+			MakeParameters
+				(Name::DecodingLookupArray(), lookup)
+				(Name::Log2Base(), log2base));
 	}
 
 	void IsolatedInitialize(const NameValuePairs &parameters);
@@ -98,7 +103,7 @@ public:
 
 private:
 	const int *m_lookup;
-	int m_padding, m_bitsPerChar, m_outputBlockSize;
+	int m_bitsPerChar, m_outputBlockSize;
 	int m_bytePos, m_bitPos;
 	SecByteBlock m_outBuf;
 };
@@ -121,9 +126,11 @@ public:
 		: m_groupSize(0), m_counter(0)
 	{
 		Detach(attachment);
-		IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize)
-			(Name::Separator(), ConstByteArrayParameter(separator))
-			(Name::Terminator(), ConstByteArrayParameter(terminator)));
+		Grouper::IsolatedInitialize(
+			MakeParameters
+				(Name::GroupSize(), groupSize)
+				(Name::Separator(), ConstByteArrayParameter(separator))
+				(Name::Terminator(), ConstByteArrayParameter(terminator)));
 	}
 
 	void IsolatedInitialize(const NameValuePairs &parameters);

+ 60 - 12
include/cryptlib/bench.h

@@ -16,14 +16,48 @@ NAMESPACE_BEGIN(Test)
 
 // More granular control over benchmarks
 enum TestClass {
-	UnkeyedRNG=(1<<0),UnkeyedHash=(1<<1),UnkeyedOther=(1<<2),
-	SharedKeyMAC=(1<<3),SharedKeyStream=(1<<4),SharedKeyBlock=(1<<5),SharedKeyOther=(1<<6),
-	PublicKeyAgreement=(1<<7),PublicKeyEncryption=(1<<8),PublicKeySignature=(1<<9),PublicKeyOther=(1<<10),
+	/// \brief Random number generators
+	UnkeyedRNG=(1<<0),
+	/// \brief Message digests
+	UnkeyedHash=(1<<1),
+	/// \brief Other unkeyed algorithms
+	UnkeyedOther=(1<<2),
+
+	/// \brief Message authentication codes
+	SharedKeyMAC=(1<<3),
+	/// \brief Stream ciphers
+	SharedKeyStream=(1<<4),
+	/// \brief Block ciphers ciphers
+	SharedKeyBlock=(1<<5),
+	/// \brief Other shared key algorithms
+	SharedKeyOther=(1<<6),
+
+	/// \brief Key agreement algorithms over integers
+	PublicKeyAgreement=(1<<7),
+	/// \brief Encryption algorithms over integers
+	PublicKeyEncryption=(1<<8),
+	/// \brief Signature algorithms over integers
+	PublicKeySignature=(1<<9),
+	/// \brief Other public key algorithms over integers
+	PublicKeyOther=(1<<10),
+
+	/// \brief Key agreement algorithms over EC
+	PublicKeyAgreementEC=(1<<11),
+	/// \brief Encryption algorithms over EC
+	PublicKeyEncryptionEC=(1<<12),
+	/// \brief Signature algorithms over EC
+	PublicKeySignatureEC=(1<<13),
+	/// \brief Other public key algorithms over EC
+	PublicKeyOtherEC=(1<<14),
+
 	Unkeyed=UnkeyedRNG|UnkeyedHash|UnkeyedOther,
 	SharedKey=SharedKeyMAC|SharedKeyStream|SharedKeyBlock|SharedKeyOther,
 	PublicKey=PublicKeyAgreement|PublicKeyEncryption|PublicKeySignature|PublicKeyOther,
-	All=Unkeyed|SharedKey|PublicKey,
-	TestFirst=(0), TestLast=(1<<11)
+	PublicKeyEC=PublicKeyAgreementEC|PublicKeyEncryptionEC|PublicKeySignatureEC|PublicKeyOtherEC,
+
+	All=Unkeyed|SharedKey|PublicKey|PublicKeyEC,
+
+	TestFirst=(0), TestLast=(1<<15)
 };
 
 extern const double CLOCK_TICKS_PER_SECOND;
@@ -37,19 +71,33 @@ extern const byte defaultKey[];
 extern time_t g_testBegin;
 extern time_t g_testEnd;
 
-// Command handler
+// Benchmark command handler
 void BenchmarkWithCommand(int argc, const char* const argv[]);
 // Top level, prints preamble and postamble
 void Benchmark(Test::TestClass suites, double t, double hertz);
 // Unkeyed systems
-void Benchmark1(double t, double hertz);
+void BenchmarkUnkeyedAlgorithms(double t, double hertz);
 // Shared key systems
-void Benchmark2(double t, double hertz);
-// Public key systems
-void Benchmark3(double t, double hertz);
+void BenchmarkSharedKeyedAlgorithms(double t, double hertz);
+// Public key systems over integers
+void BenchmarkPublicKeyAlgorithms(double t, double hertz);
+// Public key systems over elliptic curves
+void BenchmarkEllipticCurveAlgorithms(double t, double hertz);
+
+// These are defined in bench1.cpp
+extern void OutputResultKeying(double iterations, double timeTaken);
+extern void OutputResultBytes(const char *name, const char *provider, double length, double timeTaken);
+extern void OutputResultOperations(const char *name, const char *provider, const char *operation, bool pc, unsigned long iterations, double timeTaken);
+
+// These are defined in bench1.cpp
+extern void BenchMark(const char *name, BufferedTransformation &bt, double timeTotal);
+extern void BenchMark(const char *name, StreamTransformation &cipher, double timeTotal);
+extern void BenchMark(const char *name, HashTransformation &ht, double timeTotal);
+extern void BenchMark(const char *name, RandomNumberGenerator &rng, double timeTotal);
 
-void OutputResultBytes(const char *name, double length, double timeTaken);
-void OutputResultOperations(const char *name, const char *operation, bool pc, unsigned long iterations, double timeTaken);
+// These are defined in bench2.cpp
+extern void BenchMarkKeying(SimpleKeyingInterface &c, size_t keyLength, const NameValuePairs &params);
+extern void BenchMark(const char *name, AuthenticatedSymmetricCipher &cipher, double timeTotal);
 
 NAMESPACE_END  // Test
 NAMESPACE_END  // CryptoPP

+ 377 - 242
include/cryptlib/blake2.h

@@ -1,6 +1,7 @@
-// blake2.h - written and placed in the public domain by Jeffrey Walton and Zooko
-//            Wilcox-O'Hearn. Based on Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
-//            reference BLAKE2 implementation at http://github.com/BLAKE2/BLAKE2.
+// blake2.h - written and placed in the public domain by Jeffrey Walton
+//            and Zooko Wilcox-O'Hearn. Based on Aumasson, Neves,
+//            Wilcox-O'Hearn and Winnerlein's reference BLAKE2
+//            implementation at http://github.com/BLAKE2/BLAKE2.
 
 /// \file blake2.h
 /// \brief Classes for BLAKE2b and BLAKE2s message digests and keyed message digests
@@ -9,10 +10,8 @@
 ///   Static algorithm name return either "BLAKE2b" or "BLAKE2s". An object algorithm name follows
 ///   the naming described in <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The
 ///   BLAKE2 Cryptographic Hash and Message Authentication Code (MAC)</A>.
-/// \details The library provides specialized SSE2, SSE4 and NEON version of the BLAKE2 compression
-///   function. For best results under ARM NEON, specify both an architecture and cpu. For example:
-///   <pre>CXXFLAGS="-DNDEBUG -march=armv8-a+crc -mcpu=cortex-a53 ..."</pre>
-/// \since Crypto++ 5.6.4
+/// \since C++ since Crypto++ 5.6.4, SSE since Crypto++ 5.6.4, NEON since Crypto++ 6.0,
+///   Power8 since Crypto++ 8.0
 
 #ifndef CRYPTOPP_BLAKE2_H
 #define CRYPTOPP_BLAKE2_H
@@ -23,285 +22,421 @@
 
 NAMESPACE_BEGIN(CryptoPP)
 
-/// \brief BLAKE2 hash information
-/// \tparam T_64bit flag indicating 64-bit
+/// \brief BLAKE2s hash information
 /// \since Crypto++ 5.6.4
-template <bool T_64bit>
-struct BLAKE2_Info : public VariableKeyLength<(T_64bit ? 64 : 32),0,(T_64bit ? 64 : 32),1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
+struct BLAKE2s_Info : public VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
 {
-	typedef VariableKeyLength<(T_64bit ? 64 : 32),0,(T_64bit ? 64 : 32),1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
-	CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH)
-	CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH)
-	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH)
+    typedef VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
+    CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH);
+    CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH);
+    CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH);
 
-	CRYPTOPP_CONSTANT(BLOCKSIZE = (T_64bit ? 128 : 64))
-	CRYPTOPP_CONSTANT(DIGESTSIZE = (T_64bit ? 64 : 32))
-	CRYPTOPP_CONSTANT(SALTSIZE = (T_64bit ? 16 : 8))
-	CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = (T_64bit ? 16 : 8))
+    CRYPTOPP_CONSTANT(BLOCKSIZE = 64);
+    CRYPTOPP_CONSTANT(DIGESTSIZE = 32);
+    CRYPTOPP_CONSTANT(SALTSIZE = 8);
+    CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 8);
 
-	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return (T_64bit ? "BLAKE2b" : "BLAKE2s");}
+    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";}
 };
 
-/// \brief BLAKE2 parameter block
-/// \tparam T_64bit flag indicating 64-bit
-/// \details BLAKE2b uses BLAKE2_ParameterBlock<true>, while BLAKE2s
-///   uses BLAKE2_ParameterBlock<false>.
+/// \brief BLAKE2b hash information
 /// \since Crypto++ 5.6.4
-template <bool T_64bit>
-struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock
+struct BLAKE2b_Info : public VariableKeyLength<64,0,64,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
 {
+    typedef VariableKeyLength<64,0,64,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
+    CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH);
+    CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH);
+    CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH);
+
+    CRYPTOPP_CONSTANT(BLOCKSIZE = 128);
+    CRYPTOPP_CONSTANT(DIGESTSIZE = 64);
+    CRYPTOPP_CONSTANT(SALTSIZE = 16);
+    CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 16);
+
+    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2b";}
 };
 
-/// \brief BLAKE2b parameter block specialization
-template<>
-struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock<true>
+/// \brief BLAKE2s parameter block
+struct CRYPTOPP_NO_VTABLE BLAKE2s_ParameterBlock
 {
-	CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<true>::SALTSIZE)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<true>::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<true>::PERSONALIZATIONSIZE)
-
-	BLAKE2_ParameterBlock()
-	{
-		memset(this, 0x00, sizeof(*this));
-		digestLength = DIGESTSIZE;
-		fanout = depth = 1;
-	}
-
-	BLAKE2_ParameterBlock(size_t digestSize)
-	{
-		CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
-		memset(this, 0x00, sizeof(*this));
-		digestLength = (byte)digestSize;
-		fanout = depth = 1;
-	}
-
-	BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
-		const byte* personalization, size_t personalizationLength);
-
-	byte digestLength;
-	byte keyLength, fanout, depth;
-	byte leafLength[4];
-	byte nodeOffset[8];
-	byte nodeDepth, innerLength, rfu[14];
-	byte salt[SALTSIZE];
-	byte personalization[PERSONALIZATIONSIZE];
+    CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2s_Info::SALTSIZE);
+    CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2s_Info::DIGESTSIZE);
+    CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2s_Info::PERSONALIZATIONSIZE);
+
+    BLAKE2s_ParameterBlock()
+    {
+        Reset();
+    }
+
+    BLAKE2s_ParameterBlock(size_t digestSize)
+    {
+        Reset(digestSize);
+    }
+
+    BLAKE2s_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
+        const byte* personalization, size_t personalizationLength);
+
+    void Reset(size_t digestLength=DIGESTSIZE, size_t keyLength=0);
+
+    byte* data() {
+        return m_data.data();
+    }
+
+    const byte* data() const {
+        return m_data.data();
+    }
+
+    size_t size() const {
+        return m_data.size();
+    }
+
+    byte* salt() {
+        return m_data + SaltOff;
+    }
+
+    byte* personalization() {
+        return m_data + PersonalizationOff;
+    }
+
+    // Offsets into the byte array
+    enum {
+        DigestOff = 0, KeyOff = 1, FanoutOff = 2, DepthOff = 3, LeafOff = 4, NodeOff = 8,
+        NodeDepthOff = 14, InnerOff = 15, SaltOff = 16, PersonalizationOff = 24
+    };
+
+    FixedSizeAlignedSecBlock<byte, 32, true> m_data;
 };
 
-/// \brief BLAKE2s parameter block specialization
-template<>
-struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock<false>
+/// \brief BLAKE2b parameter block
+struct CRYPTOPP_NO_VTABLE BLAKE2b_ParameterBlock
 {
-	CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<false>::SALTSIZE)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<false>::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<false>::PERSONALIZATIONSIZE)
-
-	BLAKE2_ParameterBlock()
-	{
-		memset(this, 0x00, sizeof(*this));
-		digestLength = DIGESTSIZE;
-		fanout = depth = 1;
-	}
-
-	BLAKE2_ParameterBlock(size_t digestSize)
-	{
-		CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
-		memset(this, 0x00, sizeof(*this));
-		digestLength = (byte)digestSize;
-		fanout = depth = 1;
-	}
-
-	BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
-		const byte* personalization, size_t personalizationLength);
-
-	byte digestLength;
-	byte keyLength, fanout, depth;
-	byte leafLength[4];
-	byte nodeOffset[6];
-	byte nodeDepth, innerLength;
-	byte salt[SALTSIZE];
-	byte personalization[PERSONALIZATIONSIZE];
+    CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2b_Info::SALTSIZE);
+    CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2b_Info::DIGESTSIZE);
+    CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2b_Info::PERSONALIZATIONSIZE);
+
+    BLAKE2b_ParameterBlock()
+    {
+        Reset();
+    }
+
+    BLAKE2b_ParameterBlock(size_t digestSize)
+    {
+        Reset(digestSize);
+    }
+
+    BLAKE2b_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
+        const byte* personalization, size_t personalizationLength);
+
+    void Reset(size_t digestLength=DIGESTSIZE, size_t keyLength=0);
+
+    byte* data() {
+        return m_data.data();
+    }
+
+    const byte* data() const {
+        return m_data.data();
+    }
+
+    size_t size() const {
+        return m_data.size();
+    }
+
+    byte* salt() {
+        return m_data + SaltOff;
+    }
+
+    byte* personalization() {
+        return m_data + PersonalizationOff;
+    }
+
+    // Offsets into the byte array
+    enum {
+        DigestOff = 0, KeyOff = 1, FanoutOff = 2, DepthOff = 3, LeafOff = 4, NodeOff = 8,
+        NodeDepthOff = 16, InnerOff = 17, RfuOff = 18, SaltOff = 32, PersonalizationOff = 48
+    };
+
+    FixedSizeAlignedSecBlock<byte, 64, true> m_data;
 };
 
-/// \brief BLAKE2 state information
-/// \tparam W word type
-/// \tparam T_64bit flag indicating 64-bit
-/// \details BLAKE2b uses BLAKE2_State<word64, true>, while BLAKE2s
-///   uses BLAKE2_State<word32, false>.
+/// \brief BLAKE2s state information
 /// \since Crypto++ 5.6.4
-template <class W, bool T_64bit>
-struct CRYPTOPP_NO_VTABLE BLAKE2_State
+struct CRYPTOPP_NO_VTABLE BLAKE2s_State
 {
-	CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info<T_64bit>::BLOCKSIZE)
-
-	BLAKE2_State()
-	{
-		// Set all members except scratch buffer[]
-		h[0]=h[1]=h[2]=h[3]=h[4]=h[5]=h[6]=h[7] = 0;
-		t[0]=t[1]=f[0]=f[1] = 0;
-		length = 0;
-	}
-
-	// SSE2, SSE4 and NEON depend upon t[] and f[] being side-by-side
-	W h[8], t[2], f[2];
-	byte  buffer[BLOCKSIZE];
-	size_t length;
+    BLAKE2s_State() {
+        Reset();
+    }
+
+    void Reset();
+
+    inline word32* h() {
+        return m_hft.data();
+    }
+
+    inline word32* t() {
+        return m_hft.data() + 8;
+    }
+
+    inline word32* f() {
+        return m_hft.data() + 10;
+    }
+
+    inline byte* data() {
+        return m_buf.data();
+    }
+
+    // SSE4, Power7 and NEON depend upon t[] and f[] being side-by-side
+    CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2s_Info::BLOCKSIZE);
+    FixedSizeAlignedSecBlock<word32, 8+2+2, true> m_hft;
+    FixedSizeAlignedSecBlock<byte, BLOCKSIZE, true> m_buf;
+    size_t m_len;
 };
 
-/// \brief BLAKE2 hash implementation
-/// \tparam W word type
-/// \tparam T_64bit flag indicating 64-bit
-/// \details BLAKE2b uses BLAKE2_Base<word64, true>, while BLAKE2s
-///   uses BLAKE2_Base<word32, false>.
+/// \brief BLAKE2b state information
 /// \since Crypto++ 5.6.4
-template <class W, bool T_64bit>
-class BLAKE2_Base : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2_Info<T_64bit> >
+struct CRYPTOPP_NO_VTABLE BLAKE2b_State
 {
-public:
-	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2_Info<T_64bit>::DEFAULT_KEYLENGTH)
-	CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2_Info<T_64bit>::MIN_KEYLENGTH)
-	CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2_Info<T_64bit>::MAX_KEYLENGTH)
-
-	CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<T_64bit>::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info<T_64bit>::BLOCKSIZE)
-	CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<T_64bit>::SALTSIZE)
-	CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<T_64bit>::PERSONALIZATIONSIZE)
-
-	typedef BLAKE2_State<W, T_64bit> State;
-	typedef BLAKE2_ParameterBlock<T_64bit> ParameterBlock;
-	typedef SecBlock<State, AllocatorWithCleanup<State, true> > AlignedState;
-	typedef SecBlock<ParameterBlock, AllocatorWithCleanup<ParameterBlock, true> > AlignedParameterBlock;
-
-	virtual ~BLAKE2_Base() {}
-
-	/// \brief Retrieve the static algorithm name
-	/// \returns the algorithm name (BLAKE2s or BLAKE2b)
-	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return BLAKE2_Info<T_64bit>::StaticAlgorithmName();}
-
-	/// \brief Retrieve the object's name
-	/// \returns the object's algorithm name following RFC 7693
-	/// \details Object algorithm name follows the naming described in
-	///   <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
-	/// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
-	std::string AlgorithmName() const {return std::string(StaticAlgorithmName()) + "-" + IntToString(this->DigestSize()*8);}
-
-	unsigned int DigestSize() const {return m_digestSize;}
-	unsigned int OptimalDataAlignment() const {return (CRYPTOPP_BOOL_ALIGN16 ? 16 : GetAlignmentOf<W>());}
-
-	void Update(const byte *input, size_t length);
-	void Restart();
-
-	/// \brief Restart a hash with parameter block and counter
-	/// \param block parameter block
-	/// \param counter counter array
-	/// \details Parameter block is persisted across calls to Restart().
-	void Restart(const BLAKE2_ParameterBlock<T_64bit>& block, const W counter[2]);
-
-	/// \brief Set tree mode
-	/// \param mode the new tree mode
-	/// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
-	///   If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
-	///   <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
-	///   Tree mode is persisted across calls to Restart().
-	void SetTreeMode(bool mode) {m_treeMode=mode;}
-
-	/// \brief Get tree mode
-	/// \returns the current tree mode
-	/// \details Tree mode is persisted across calls to Restart().
-	bool GetTreeMode() const {return m_treeMode;}
-
-	void TruncatedFinal(byte *hash, size_t size);
+    BLAKE2b_State() {
+        Reset();
+    }
 
-protected:
-	BLAKE2_Base();
-	BLAKE2_Base(bool treeMode, unsigned int digestSize);
-	BLAKE2_Base(const byte *key, size_t keyLength, const byte* salt, size_t saltLength,
-		const byte* personalization, size_t personalizationLength,
-		bool treeMode, unsigned int digestSize);
+    void Reset();
 
-	// Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
-	void Compress(const byte *input);
-	inline void IncrementCounter(size_t count=BLOCKSIZE);
+    inline word64* h() {
+        return m_hft.data();
+    }
 
-	void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
+    inline word64* t() {
+        return m_hft.data() + 8;
+    }
 
-private:
-	AlignedState m_state;
-	AlignedParameterBlock m_block;
-	AlignedSecByteBlock m_key;
-	word32 m_digestSize;
-	bool m_treeMode;
+    inline word64* f() {
+        return m_hft.data() + 10;
+    }
+
+    inline byte* data() {
+        return m_buf.data();
+    }
+
+    // SSE4, Power8 and NEON depend upon t[] and f[] being side-by-side
+    CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2b_Info::BLOCKSIZE);
+    FixedSizeAlignedSecBlock<word64, 8+2+2, true> m_hft;
+    FixedSizeAlignedSecBlock<byte, BLOCKSIZE, true> m_buf;
+    size_t m_len;
 };
 
-/// \brief The BLAKE2b cryptographic hash function
-/// \details BLAKE2b can function as both a hash and keyed hash. If you want only the hash,
-///   then use the BLAKE2b constructor that accepts no parameters or digest size. If you
+/// \brief The BLAKE2s cryptographic hash function
+/// \details BLAKE2s can function as both a hash and keyed hash. If you want only the hash,
+///   then use the BLAKE2s constructor that accepts no parameters or digest size. If you
 ///   want a keyed hash, then use the constructor that accpts the key as a parameter.
 ///   Once a key and digest size are selected, its effectively immutable. The Restart()
 ///   method that accepts a ParameterBlock does not allow you to change it.
 /// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
 ///   <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
-/// \since Crypto++ 5.6.4
-class BLAKE2b : public BLAKE2_Base<word64, true>
+/// \since C++ since Crypto++ 5.6.4, SSE since Crypto++ 5.6.4, NEON since Crypto++ 6.0,
+///   Power8 since Crypto++ 8.0
+class BLAKE2s : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2s_Info>
 {
 public:
-	typedef BLAKE2_Base<word64, true> ThisBase; // Early Visual Studio workaround
-	typedef BLAKE2_ParameterBlock<true> ParameterBlock;
-	CRYPTOPP_COMPILE_ASSERT(sizeof(ParameterBlock) == 64);
-
-	/// \brief Construct a BLAKE2b hash
-	/// \param digestSize the digest size, in bytes
-	/// \param treeMode flag indicating tree mode
-	BLAKE2b(bool treeMode=false, unsigned int digestSize = DIGESTSIZE) : ThisBase(treeMode, digestSize) {}
-
-	/// \brief Construct a BLAKE2b hash
-	/// \param key a byte array used to key the cipher
-	/// \param keyLength the size of the byte array
-	/// \param salt a byte array used as salt
-	/// \param saltLength the size of the byte array
-	/// \param personalization a byte array used as prsonalization string
-	/// \param personalizationLength the size of the byte array
-	/// \param treeMode flag indicating tree mode
-	/// \param digestSize the digest size, in bytes
-	BLAKE2b(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
-		const byte* personalization = NULLPTR, size_t personalizationLength = 0,
-		bool treeMode=false, unsigned int digestSize = DIGESTSIZE)
-		: ThisBase(key, keyLength, salt, saltLength, personalization, personalizationLength, treeMode, digestSize) {}
+    CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2s_Info::DEFAULT_KEYLENGTH);
+    CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2s_Info::MIN_KEYLENGTH);
+    CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2s_Info::MAX_KEYLENGTH);
+
+    CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2s_Info::DIGESTSIZE);
+    CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2s_Info::BLOCKSIZE);
+    CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2s_Info::SALTSIZE);
+    CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2s_Info::PERSONALIZATIONSIZE);
+
+    typedef BLAKE2s_State State;
+    typedef BLAKE2s_ParameterBlock ParameterBlock;
+
+    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";}
+
+    virtual ~BLAKE2s() {}
+
+    /// \brief Construct a BLAKE2s hash
+    /// \param digestSize the digest size, in bytes
+    /// \param treeMode flag indicating tree mode
+    /// \since Crypto++ 5.6.4
+    BLAKE2s(bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
+
+    /// \brief Construct a BLAKE2s hash
+    /// \param digestSize the digest size, in bytes
+    /// \details treeMode flag is set to false
+    /// \since Crypto++ 8.2
+    BLAKE2s(unsigned int digestSize);
+
+    /// \brief Construct a BLAKE2s hash
+    /// \param key a byte array used to key the cipher
+    /// \param keyLength the size of the byte array
+    /// \param salt a byte array used as salt
+    /// \param saltLength the size of the byte array
+    /// \param personalization a byte array used as personalization string
+    /// \param personalizationLength the size of the byte array
+    /// \param treeMode flag indicating tree mode
+    /// \param digestSize the digest size, in bytes
+    /// \since Crypto++ 5.6.4
+    BLAKE2s(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
+        const byte* personalization = NULLPTR, size_t personalizationLength = 0,
+        bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
+
+    /// \brief Retrieve the object's name
+    /// \return the object's algorithm name following RFC 7693
+    /// \details Object algorithm name follows the naming described in
+    ///   <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
+    /// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
+    std::string AlgorithmName() const {return std::string(BLAKE2s_Info::StaticAlgorithmName()) + "-" + IntToString(DigestSize()*8);}
+
+    unsigned int BlockSize() const {return BLOCKSIZE;}
+    unsigned int DigestSize() const {return m_digestSize;}
+    unsigned int OptimalDataAlignment() const;
+
+    void Update(const byte *input, size_t length);
+    void Restart();
+
+    /// \brief Restart a hash with parameter block and counter
+    /// \param block parameter block
+    /// \param counter counter array
+    /// \details Parameter block is persisted across calls to Restart().
+    void Restart(const BLAKE2s_ParameterBlock& block, const word32 counter[2]);
+
+    /// \brief Set tree mode
+    /// \param mode the new tree mode
+    /// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
+    ///   If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
+    ///   <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
+    ///   Tree mode is persisted across calls to Restart().
+    void SetTreeMode(bool mode) {m_treeMode=mode;}
+
+    /// \brief Get tree mode
+    /// \return the current tree mode
+    /// \details Tree mode is persisted across calls to Restart().
+    bool GetTreeMode() const {return m_treeMode;}
+
+    void TruncatedFinal(byte *hash, size_t size);
+
+    std::string AlgorithmProvider() const;
+
+protected:
+    // Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
+    void Compress(const byte *input);
+    inline void IncrementCounter(size_t count=BLOCKSIZE);
+
+    void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
+
+private:
+    State m_state;
+    ParameterBlock m_block;
+    AlignedSecByteBlock m_key;
+    word32 m_digestSize, m_keyLength;
+    bool m_treeMode;
 };
 
-/// \brief The BLAKE2s cryptographic hash function
-/// \details BLAKE2s can function as both a hash and keyed hash. If you want only the hash,
-///   then use the BLAKE2s constructor that accepts no parameters or digest size. If you
+/// \brief The BLAKE2b cryptographic hash function
+/// \details BLAKE2b can function as both a hash and keyed hash. If you want only the hash,
+///   then use the BLAKE2b constructor that accepts no parameters or digest size. If you
 ///   want a keyed hash, then use the constructor that accpts the key as a parameter.
 ///   Once a key and digest size are selected, its effectively immutable. The Restart()
 ///   method that accepts a ParameterBlock does not allow you to change it.
 /// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
 ///   <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
-/// \since Crypto++ 5.6.4
-class BLAKE2s : public BLAKE2_Base<word32, false>
+/// \since C++ since Crypto++ 5.6.4, SSE since Crypto++ 5.6.4, NEON since Crypto++ 6.0,
+///   Power8 since Crypto++ 8.0
+class BLAKE2b : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2b_Info>
 {
 public:
-	typedef BLAKE2_Base<word32, false> ThisBase; // Early Visual Studio workaround
-	typedef BLAKE2_ParameterBlock<false> ParameterBlock;
-	CRYPTOPP_COMPILE_ASSERT(sizeof(ParameterBlock) == 32);
-
-	/// \brief Construct a BLAKE2s hash
-	/// \param digestSize the digest size, in bytes
-	/// \param treeMode flag indicating tree mode
-	BLAKE2s(bool treeMode=false, unsigned int digestSize = DIGESTSIZE) : ThisBase(treeMode, digestSize) {}
-
-	/// \brief Construct a BLAKE2s hash
-	/// \param key a byte array used to key the cipher
-	/// \param keyLength the size of the byte array
-	/// \param salt a byte array used as salt
-	/// \param saltLength the size of the byte array
-	/// \param personalization a byte array used as prsonalization string
-	/// \param personalizationLength the size of the byte array
-	/// \param treeMode flag indicating tree mode
-	/// \param digestSize the digest size, in bytes
-	BLAKE2s(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
-		const byte* personalization = NULLPTR, size_t personalizationLength = 0,
-		bool treeMode=false, unsigned int digestSize = DIGESTSIZE)
-		: ThisBase(key, keyLength, salt, saltLength, personalization, personalizationLength, treeMode, digestSize) {}
+    CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2b_Info::DEFAULT_KEYLENGTH);
+    CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2b_Info::MIN_KEYLENGTH);
+    CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2b_Info::MAX_KEYLENGTH);
+
+    CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2b_Info::DIGESTSIZE);
+    CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2b_Info::BLOCKSIZE);
+    CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2b_Info::SALTSIZE);
+    CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2b_Info::PERSONALIZATIONSIZE);
+
+    typedef BLAKE2b_State State;
+    typedef BLAKE2b_ParameterBlock ParameterBlock;
+
+    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2b";}
+
+    virtual ~BLAKE2b() {}
+
+    /// \brief Construct a BLAKE2b hash
+    /// \param digestSize the digest size, in bytes
+    /// \param treeMode flag indicating tree mode
+    /// \since Crypto++ 5.6.4
+    BLAKE2b(bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
+
+    /// \brief Construct a BLAKE2s hash
+    /// \param digestSize the digest size, in bytes
+    /// \details treeMode flag is set to false
+    /// \since Crypto++ 8.2
+    BLAKE2b(unsigned int digestSize);
+
+    /// \brief Construct a BLAKE2b hash
+    /// \param key a byte array used to key the cipher
+    /// \param keyLength the size of the byte array
+    /// \param salt a byte array used as salt
+    /// \param saltLength the size of the byte array
+    /// \param personalization a byte array used as personalization string
+    /// \param personalizationLength the size of the byte array
+    /// \param treeMode flag indicating tree mode
+    /// \param digestSize the digest size, in bytes
+    /// \since Crypto++ 5.6.4
+    BLAKE2b(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
+        const byte* personalization = NULLPTR, size_t personalizationLength = 0,
+        bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
+
+    /// \brief Retrieve the object's name
+    /// \return the object's algorithm name following RFC 7693
+    /// \details Object algorithm name follows the naming described in
+    ///   <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
+    /// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
+    std::string AlgorithmName() const {return std::string(BLAKE2b_Info::StaticAlgorithmName()) + "-" + IntToString(DigestSize()*8);}
+
+    unsigned int BlockSize() const {return BLOCKSIZE;}
+    unsigned int DigestSize() const {return m_digestSize;}
+    unsigned int OptimalDataAlignment() const;
+
+    void Update(const byte *input, size_t length);
+    void Restart();
+
+    /// \brief Restart a hash with parameter block and counter
+    /// \param block parameter block
+    /// \param counter counter array
+    /// \details Parameter block is persisted across calls to Restart().
+    void Restart(const BLAKE2b_ParameterBlock& block, const word64 counter[2]);
+
+    /// \brief Set tree mode
+    /// \param mode the new tree mode
+    /// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
+    ///   If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
+    ///   <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
+    ///   Tree mode is persisted across calls to Restart().
+    void SetTreeMode(bool mode) {m_treeMode=mode;}
+
+    /// \brief Get tree mode
+    /// \return the current tree mode
+    /// \details Tree mode is persisted across calls to Restart().
+    bool GetTreeMode() const {return m_treeMode;}
+
+    void TruncatedFinal(byte *hash, size_t size);
+
+    std::string AlgorithmProvider() const;
+
+protected:
+
+    // Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
+    void Compress(const byte *input);
+    inline void IncrementCounter(size_t count=BLOCKSIZE);
+
+    void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
+
+private:
+    State m_state;
+    ParameterBlock m_block;
+    AlignedSecByteBlock m_key;
+    word32 m_digestSize, m_keyLength;
+    bool m_treeMode;
 };
 
 NAMESPACE_END

+ 16 - 4
include/cryptlib/blumshub.h

@@ -12,13 +12,19 @@
 
 NAMESPACE_BEGIN(CryptoPP)
 
-/// BlumBlumShub without factorization of the modulus
+/// \brief BlumBlumShub without factorization of the modulus
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 class PublicBlumBlumShub : public RandomNumberGenerator,
 						   public StreamTransformation
 {
 public:
 	virtual ~PublicBlumBlumShub() {}
 
+	/// \brief Construct a PublicBlumBlumShub
+	/// \param n the modulus
+	/// \param seed the seed for the generator
+	/// \details seed is the secret key and should be about as large as n.
 	PublicBlumBlumShub(const Integer &n, const Integer &seed);
 
 	unsigned int GenerateBit();
@@ -35,14 +41,20 @@ protected:
 	word maxBits, bitsLeft;
 };
 
-/// BlumBlumShub with factorization of the modulus
+/// \brief BlumBlumShub with factorization of the modulus
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 class BlumBlumShub : public PublicBlumBlumShub
 {
 public:
 	virtual ~BlumBlumShub() {}
 
-	// Make sure p and q are both primes congruent to 3 mod 4 and at least 512 bits long,
-	// seed is the secret key and should be about as big as p*q
+	/// \brief Construct a BlumBlumShub
+	/// \param p the first prime factor
+	/// \param q the second prime factor
+	/// \param seed the seed for the generator
+	/// \details Esure p and q are both primes congruent to 3 mod 4 and at least 512 bits long.
+	///  seed is the secret key and should be about as large as p*q.
 	BlumBlumShub(const Integer &p, const Integer &q, const Integer &seed);
 
 	bool IsRandomAccess() const {return true;}

+ 4 - 0
include/cryptlib/cbcmac.h

@@ -43,7 +43,11 @@ template <class T>
 class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
 {
 public:
+	/// \brief Construct a CBC_MAC
 	CBC_MAC() {}
+	/// \brief Construct a CBC_MAC
+	/// \param key a byte buffer used to key the cipher
+	/// \param length the length of the byte buffer
 	CBC_MAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
 		{this->SetKey(key, length);}
 

+ 3 - 1
include/cryptlib/ccm.h

@@ -24,6 +24,8 @@ public:
 	// AuthenticatedSymmetricCipher
 	std::string AlgorithmName() const
 		{return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
+	std::string AlgorithmProvider() const
+		{return GetBlockCipher().AlgorithmProvider();}
 	size_t MinKeyLength() const
 		{return GetBlockCipher().MinKeyLength();}
 	size_t MaxKeyLength() const
@@ -71,7 +73,7 @@ protected:
 	virtual BlockCipher & AccessBlockCipher() =0;
 	virtual int DefaultDigestSize() const =0;
 
-	const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
+	const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();}
 	byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
 
 	enum {REQUIRED_BLOCKSIZE = 16};

+ 183 - 45
include/cryptlib/chacha.h

@@ -1,14 +1,30 @@
 // chacha.h - written and placed in the public domain by Jeffrey Walton.
-//            Based on Wei Dai's Salsa20 and Bernstein's reference ChaCha
-//            family implementation at http://cr.yp.to/chacha.html.
+//            Based on Wei Dai's Salsa20, Botan's SSE2 implementation,
+//            and Bernstein's reference ChaCha family implementation at
+//            http://cr.yp.to/chacha.html.
+
+// The library added Bernstein's ChaCha classes at Crypto++ 5.6.4. The IETF
+// uses a slightly different implementation than Bernstein, and the IETF
+// ChaCha and XChaCha classes were added at Crypto++ 8.1. We wanted to maintain
+// ABI compatibility at the 8.1 release so the original ChaCha classes were not
+// disturbed. Instead new classes were added for IETF ChaCha. The back-end
+// implementation shares code as expected, however.
 
 /// \file chacha.h
 /// \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers
-/// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha,
-///   a variant of Salsa20</a> (2008.01.28). Bernstein's implementation is _slightly_ different from the TLS working group's
-///   implementation for cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
-///   <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
-/// \since Crypto++ 5.6.4
+/// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a
+///  href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a
+///  variant of Salsa20</a> (2008.01.28). Crypto++ also provides the
+///  IETF implementation of ChaCha using the ChaChaTLS name. Bernstein's
+///  implementation is _slightly_ different from the TLS working group's
+///  implementation for cipher suites
+///  <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
+///  <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
+///  and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>. Finally,
+///  the library provides <a
+///  href="https://tools.ietf.org/html/draft-arciszewski-xchacha">XChaCha:
+///  eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03)</a>.
+/// \since ChaCha since Crypto++ 5.6.4, ChaChaTLS and XChaCha20 since Crypto++ 8.1
 
 #ifndef CRYPTOPP_CHACHA_H
 #define CRYPTOPP_CHACHA_H
@@ -18,66 +34,188 @@
 
 NAMESPACE_BEGIN(CryptoPP)
 
+////////////////////////////// Bernstein ChaCha //////////////////////////////
+
 /// \brief ChaCha stream cipher information
 /// \since Crypto++ 5.6.4
-template <unsigned int R>
-struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>, public FixedRounds<R>
+struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>
 {
-	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {
-		return (R==8?"ChaCha8":(R==12?"ChaCha12":(R==20?"ChaCha20":"ChaCha")));
-	}
+    /// \brief The algorithm name
+    /// \return the algorithm name
+    /// \details StaticAlgorithmName returns the algorithm's name as a static
+    ///  member function.
+    /// \details Bernstein named the cipher variants ChaCha8, ChaCha12 and
+    ///  ChaCha20. More generally, Bernstein called the family ChaCha{r}.
+    ///  AlgorithmName() provides the exact name once rounds are set.
+    static const char* StaticAlgorithmName() {
+        return "ChaCha";
+    }
 };
 
 /// \brief ChaCha stream cipher implementation
 /// \since Crypto++ 5.6.4
-template <unsigned int R>
 class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16>
 {
+public:
+    virtual ~ChaCha_Policy() {}
+    ChaCha_Policy() : m_rounds(ROUNDS) {}
+
 protected:
-	CRYPTOPP_CONSTANT(ROUNDS=FixedRounds<R>::ROUNDS)
+    void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+    void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+    void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
+    bool CipherIsRandomAccess() const {return true;}
+    void SeekToIteration(lword iterationCount);
+    unsigned int GetAlignment() const;
+    unsigned int GetOptimalBlockSize() const;
 
-	void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
-	void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
-	void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
-	bool CipherIsRandomAccess() const {return false;} // TODO
-	void SeekToIteration(lword iterationCount);
-	unsigned int GetAlignment() const;
-	unsigned int GetOptimalBlockSize() const;
+    std::string AlgorithmName() const;
+    std::string AlgorithmProvider() const;
 
-	FixedSizeAlignedSecBlock<word32, 16> m_state;
+    CRYPTOPP_CONSTANT(ROUNDS = 20);  // Default rounds
+    FixedSizeAlignedSecBlock<word32, 16> m_state;
+    unsigned int m_rounds;
 };
 
-/// \brief ChaCha8 stream cipher
-/// \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
+/// \brief ChaCha stream cipher
+/// \details This is Bernstein and ECRYPT's ChaCha. It is _slightly_ different
+///  from the IETF's version of ChaCha called ChaChaTLS.
+/// \sa <a href="http://cr.yp.to/chacha/chacha-20080208.pdf">ChaCha, a variant
+///  of Salsa20</a> (2008.01.28).
 /// \since Crypto++ 5.6.4
-struct ChaCha8 : public ChaCha_Info<8>, public SymmetricCipherDocumentation
+struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation
 {
-	typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<8>, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Encryption;
-	typedef Encryption Decryption;
+    /// \brief ChaCha Encryption
+    typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy, AdditiveCipherTemplate<> >, ChaCha_Info > Encryption;
+    /// \brief ChaCha Decryption
+    typedef Encryption Decryption;
 };
 
-/// \brief ChaCha12 stream cipher
-/// \details Bernstein and ECRYPT's ChaCha is _slightly_ different from the TLS working group's implementation for
-///   cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
-///   <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
-/// \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
-/// \since Crypto++ 5.6.4
-struct ChaCha12 : public ChaCha_Info<12>, public SymmetricCipherDocumentation
+////////////////////////////// IETF ChaChaTLS //////////////////////////////
+
+/// \brief IETF ChaCha20 stream cipher information
+/// \since Crypto++ 8.1
+struct ChaChaTLS_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 12>, FixedRounds<20>
 {
-	typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<12>, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Encryption;
-	typedef Encryption Decryption;
+    /// \brief The algorithm name
+    /// \return the algorithm name
+    /// \details StaticAlgorithmName returns the algorithm's name as a static
+    ///  member function.
+    /// \details This is the IETF's variant of Bernstein's ChaCha from RFC
+    ///  8439. IETF ChaCha is called ChaChaTLS in the Crypto++ library. It
+    ///  is _slightly_ different from Bernstein's implementation.
+    static const char* StaticAlgorithmName() {
+        return "ChaChaTLS";
+    }
 };
 
-/// \brief ChaCha20 stream cipher
-/// \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
-/// \details Bernstein and ECRYPT's ChaCha is _slightly_ different from the TLS working group's implementation for
-///   cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
-///   <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
-/// \since Crypto++ 5.6.4
-struct ChaCha20 : public ChaCha_Info<20>, public SymmetricCipherDocumentation
+/// \brief IETF ChaCha20 stream cipher implementation
+/// \since Crypto++ 8.1
+class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy<word32, 16>
+{
+public:
+    virtual ~ChaChaTLS_Policy() {}
+    ChaChaTLS_Policy() : m_counter(0) {}
+
+protected:
+    void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+    void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+    void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
+    bool CipherIsRandomAccess() const {return true;}
+    void SeekToIteration(lword iterationCount);
+    unsigned int GetAlignment() const;
+    unsigned int GetOptimalBlockSize() const;
+
+    std::string AlgorithmName() const;
+    std::string AlgorithmProvider() const;
+
+    FixedSizeAlignedSecBlock<word32, 16+8> m_state;
+    unsigned int m_counter;
+    CRYPTOPP_CONSTANT(ROUNDS = ChaChaTLS_Info::ROUNDS);
+    CRYPTOPP_CONSTANT(KEY = 16);  // Index into m_state
+    CRYPTOPP_CONSTANT(CTR = 24);  // Index into m_state
+};
+
+/// \brief IETF ChaCha20 stream cipher
+/// \details This is the IETF's variant of Bernstein's ChaCha from RFC 8439.
+///  IETF ChaCha is called ChaChaTLS in the Crypto++ library. It is
+///  _slightly_ different from the Bernstein implementation. ChaCha-TLS
+///  can be used for cipher suites
+///  <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
+///  <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and
+///  <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
+/// \sa <a href="https://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and
+///  Poly1305 for IETF Protocols</a>, <A
+///  HREF="https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU">How
+///  to handle block counter wrap in IETF's ChaCha algorithm?</A> and
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/790">Issue
+///  790, ChaChaTLS results when counter block wraps</A>.
+/// \since Crypto++ 8.1
+struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation
+{
+    /// \brief ChaCha-TLS Encryption
+    typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaChaTLS_Policy, AdditiveCipherTemplate<> >, ChaChaTLS_Info > Encryption;
+    /// \brief ChaCha-TLS Decryption
+    typedef Encryption Decryption;
+};
+
+////////////////////////////// IETF XChaCha20 draft //////////////////////////////
+
+/// \brief IETF XChaCha20 stream cipher information
+/// \since Crypto++ 8.1
+struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24>
+{
+    /// \brief The algorithm name
+    /// \return the algorithm name
+    /// \details StaticAlgorithmName returns the algorithm's name as a static
+    ///  member function.
+    /// \details This is the IETF's XChaCha from draft-arciszewski-xchacha.
+    static const char* StaticAlgorithmName() {
+        return "XChaCha20";
+    }
+};
+
+/// \brief IETF XChaCha20 stream cipher implementation
+/// \since Crypto++ 8.1
+class CRYPTOPP_NO_VTABLE XChaCha20_Policy : public AdditiveCipherConcretePolicy<word32, 16>
+{
+public:
+    virtual ~XChaCha20_Policy() {}
+    XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {}
+
+protected:
+    void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+    void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+    void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
+    bool CipherIsRandomAccess() const {return false;}
+    void SeekToIteration(lword iterationCount);
+    unsigned int GetAlignment() const;
+    unsigned int GetOptimalBlockSize() const;
+
+    std::string AlgorithmName() const;
+    std::string AlgorithmProvider() const;
+
+    FixedSizeAlignedSecBlock<word32, 16+8> m_state;
+    unsigned int m_counter, m_rounds;
+    CRYPTOPP_CONSTANT(ROUNDS = 20);  // Default rounds
+    CRYPTOPP_CONSTANT(KEY = 16);  // Index into m_state
+};
+
+/// \brief IETF XChaCha20 stream cipher
+/// \details This is the IETF's XChaCha from draft-arciszewski-xchacha.
+/// \sa <a href="https://tools.ietf.org/html/draft-arciszewski-xchacha">XChaCha:
+///  eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03)</a>, <A
+///  HREF="https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU">How
+///  to handle block counter wrap in IETF's ChaCha algorithm?</A> and
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/790">Issue
+///  790, ChaCha20 results when counter block wraps</A>.
+/// \since Crypto++ 8.1
+struct XChaCha20 : public XChaCha20_Info, public SymmetricCipherDocumentation
 {
-	typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<20>, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Encryption;
-	typedef Encryption Decryption;
+    /// \brief XChaCha Encryption
+    typedef SymmetricCipherFinal<ConcretePolicyHolder<XChaCha20_Policy, AdditiveCipherTemplate<> >, XChaCha20_Info > Encryption;
+    /// \brief XChaCha Decryption
+    typedef Encryption Decryption;
 };
 
 NAMESPACE_END

+ 322 - 0
include/cryptlib/chachapoly.h

@@ -0,0 +1,322 @@
+// chachapoly.h - written and placed in the public domain by Jeffrey Walton
+//                RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439
+
+/// \file chachapoly.h
+/// \brief IETF ChaCha20/Poly1305 AEAD scheme
+/// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
+///  ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
+///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
+///  and Poly1305.
+/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
+///  for IETF Protocols</A>.
+/// \since Crypto++ 8.1
+
+#ifndef CRYPTOPP_CHACHA_POLY1305_H
+#define CRYPTOPP_CHACHA_POLY1305_H
+
+#include "cryptlib.h"
+#include "authenc.h"
+#include "chacha.h"
+#include "poly1305.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+////////////////////////////// IETF ChaChaTLS //////////////////////////////
+
+/// \brief IETF ChaCha20Poly1305 cipher base implementation
+/// \details Base implementation of the AuthenticatedSymmetricCipher interface
+/// \since Crypto++ 8.1
+class ChaCha20Poly1305_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName()
+		{return "ChaCha20/Poly1305";}
+
+	virtual ~ChaCha20Poly1305_Base() {}
+
+	// AuthenticatedSymmetricCipher
+	std::string AlgorithmName() const
+		{return std::string("ChaCha20/Poly1305");}
+	std::string AlgorithmProvider() const
+		{return GetSymmetricCipher().AlgorithmProvider();}
+	size_t MinKeyLength() const
+		{return 32;}
+	size_t MaxKeyLength() const
+		{return 32;}
+	size_t DefaultKeyLength() const
+		{return 32;}
+	size_t GetValidKeyLength(size_t n) const
+		{CRYPTOPP_UNUSED(n); return 32;}
+	bool IsValidKeyLength(size_t n) const
+		{return n==32;}
+	unsigned int OptimalDataAlignment() const
+		{return GetSymmetricCipher().OptimalDataAlignment();}
+	IV_Requirement IVRequirement() const
+		{return UNIQUE_IV;}
+	unsigned int IVSize() const
+		{return 12;}
+	unsigned int MinIVLength() const
+		{return 12;}
+	unsigned int MaxIVLength() const
+		{return 12;}
+	unsigned int DigestSize() const
+		{return 16;}
+	lword MaxHeaderLength() const
+		{return LWORD_MAX;}  // 2^64-1 bytes
+	lword MaxMessageLength() const
+		{return W64LIT(274877906880);}  // 2^38-1 blocks
+	lword MaxFooterLength() const
+		{return 0;}
+
+	/// \brief Encrypts and calculates a MAC in one call
+	/// \param ciphertext the encryption buffer
+	/// \param mac the mac buffer
+	/// \param macSize the size of the MAC buffer, in bytes
+	/// \param iv the iv buffer
+	/// \param ivLength the size of the IV buffer, in bytes
+	/// \param aad the AAD buffer
+	/// \param aadLength the size of the AAD buffer, in bytes
+	/// \param message the message buffer
+	/// \param messageLength the size of the messagetext buffer, in bytes
+	/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
+	///   truncates the MAC if <tt>macSize < TagSize()</tt>.
+	virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength);
+
+	/// \brief Decrypts and verifies a MAC in one call
+	/// \param message the decryption buffer
+	/// \param mac the mac buffer
+	/// \param macSize the size of the MAC buffer, in bytes
+	/// \param iv the iv buffer
+	/// \param ivLength the size of the IV buffer, in bytes
+	/// \param aad the AAD buffer
+	/// \param aadLength the size of the AAD buffer, in bytes
+	/// \param ciphertext the cipher buffer
+	/// \param ciphertextLength the size of the ciphertext buffer, in bytes
+	/// \return true if the MAC is valid and the decoding succeeded, false otherwise
+	/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
+	/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
+	/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
+	///  is truncated if <tt>macLength < TagSize()</tt>.
+	virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength);
+
+protected:
+	// AuthenticatedSymmetricCipherBase
+	bool AuthenticationIsOnPlaintext() const {return false;}
+	unsigned int AuthenticationBlockSize() const {return 1;}
+	void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+	void Resync(const byte *iv, size_t len);
+	size_t AuthenticateBlocks(const byte *data, size_t len);
+	void AuthenticateLastHeaderBlock();
+	void AuthenticateLastConfidentialBlock();
+	void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+
+	// See comments in chachapoly.cpp
+	void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs &params);
+
+	virtual const MessageAuthenticationCode & GetMAC() const = 0;
+	virtual MessageAuthenticationCode & AccessMAC() = 0;
+
+private:
+	SecByteBlock m_userKey;
+};
+
+/// \brief IETF ChaCha20Poly1305 cipher final implementation
+/// \tparam T_IsEncryption flag indicating cipher direction
+/// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
+///  ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
+///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
+///  and Poly1305.
+/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
+///  for IETF Protocols</A>.
+/// \since Crypto++ 8.1
+template <bool T_IsEncryption>
+class ChaCha20Poly1305_Final : public ChaCha20Poly1305_Base
+{
+public:
+	virtual ~ChaCha20Poly1305_Final() {}
+
+protected:
+	const SymmetricCipher & GetSymmetricCipher()
+		{return const_cast<ChaCha20Poly1305_Final *>(this)->AccessSymmetricCipher();}
+	SymmetricCipher & AccessSymmetricCipher()
+		{return m_cipher;}
+	bool IsForwardTransformation() const
+		{return T_IsEncryption;}
+
+	const MessageAuthenticationCode & GetMAC() const
+		{return const_cast<ChaCha20Poly1305_Final *>(this)->AccessMAC();}
+	MessageAuthenticationCode & AccessMAC()
+		{return m_mac;}
+
+private:
+	ChaChaTLS::Encryption m_cipher;
+	Poly1305TLS m_mac;
+};
+
+/// \brief IETF ChaCha20/Poly1305 AEAD scheme
+/// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
+///  ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
+///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
+///  and Poly1305.
+/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
+///  for IETF Protocols</A>.
+/// \since Crypto++ 8.1
+struct ChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation
+{
+	/// \brief ChaCha20Poly1305 encryption
+	typedef ChaCha20Poly1305_Final<true> Encryption;
+	/// \brief ChaCha20Poly1305 decryption
+	typedef ChaCha20Poly1305_Final<false> Decryption;
+};
+
+////////////////////////////// IETF XChaCha20 draft //////////////////////////////
+
+/// \brief IETF XChaCha20Poly1305 cipher base implementation
+/// \details Base implementation of the AuthenticatedSymmetricCipher interface
+/// \since Crypto++ 8.1
+class XChaCha20Poly1305_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName()
+		{return "XChaCha20/Poly1305";}
+
+	virtual ~XChaCha20Poly1305_Base() {}
+
+	// AuthenticatedSymmetricCipher
+	std::string AlgorithmName() const
+		{return std::string("XChaCha20/Poly1305");}
+	std::string AlgorithmProvider() const
+		{return GetSymmetricCipher().AlgorithmProvider();}
+	size_t MinKeyLength() const
+		{return 32;}
+	size_t MaxKeyLength() const
+		{return 32;}
+	size_t DefaultKeyLength() const
+		{return 32;}
+	size_t GetValidKeyLength(size_t n) const
+		{CRYPTOPP_UNUSED(n); return 32;}
+	bool IsValidKeyLength(size_t n) const
+		{return n==32;}
+	unsigned int OptimalDataAlignment() const
+		{return GetSymmetricCipher().OptimalDataAlignment();}
+	IV_Requirement IVRequirement() const
+		{return UNIQUE_IV;}
+	unsigned int IVSize() const
+		{return 24;}
+	unsigned int MinIVLength() const
+		{return 24;}
+	unsigned int MaxIVLength() const
+		{return 24;}
+	unsigned int DigestSize() const
+		{return 16;}
+	lword MaxHeaderLength() const
+		{return LWORD_MAX;}  // 2^64-1 bytes
+	lword MaxMessageLength() const
+		{return W64LIT(274877906880);}  // 2^38-1 blocks
+	lword MaxFooterLength() const
+		{return 0;}
+
+	/// \brief Encrypts and calculates a MAC in one call
+	/// \param ciphertext the encryption buffer
+	/// \param mac the mac buffer
+	/// \param macSize the size of the MAC buffer, in bytes
+	/// \param iv the iv buffer
+	/// \param ivLength the size of the IV buffer, in bytes
+	/// \param aad the AAD buffer
+	/// \param aadLength the size of the AAD buffer, in bytes
+	/// \param message the message buffer
+	/// \param messageLength the size of the messagetext buffer, in bytes
+	/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
+	///   truncates the MAC if <tt>macSize < TagSize()</tt>.
+	virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength);
+
+	/// \brief Decrypts and verifies a MAC in one call
+	/// \param message the decryption buffer
+	/// \param mac the mac buffer
+	/// \param macSize the size of the MAC buffer, in bytes
+	/// \param iv the iv buffer
+	/// \param ivLength the size of the IV buffer, in bytes
+	/// \param aad the AAD buffer
+	/// \param aadLength the size of the AAD buffer, in bytes
+	/// \param ciphertext the cipher buffer
+	/// \param ciphertextLength the size of the ciphertext buffer, in bytes
+	/// \return true if the MAC is valid and the decoding succeeded, false otherwise
+	/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
+	/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
+	/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
+	///  is truncated if <tt>macLength < TagSize()</tt>.
+	virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength);
+
+protected:
+	// AuthenticatedSymmetricCipherBase
+	bool AuthenticationIsOnPlaintext() const {return false;}
+	unsigned int AuthenticationBlockSize() const {return 1;}
+	void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+	void Resync(const byte *iv, size_t len);
+	size_t AuthenticateBlocks(const byte *data, size_t len);
+	void AuthenticateLastHeaderBlock();
+	void AuthenticateLastConfidentialBlock();
+	void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+
+	// See comments in chachapoly.cpp
+	void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs &params);
+
+	virtual const MessageAuthenticationCode & GetMAC() const = 0;
+	virtual MessageAuthenticationCode & AccessMAC() = 0;
+
+private:
+	SecByteBlock m_userKey;
+};
+
+/// \brief IETF XChaCha20Poly1305 cipher final implementation
+/// \tparam T_IsEncryption flag indicating cipher direction
+/// \details XChaCha20Poly1305 is an authenticated encryption scheme that combines
+///  XChaCha20 and Poly1305-TLS. The scheme is defined in RFC 8439, section 2.8,
+///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
+///  and Poly1305.
+/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
+///  for IETF Protocols</A>.
+/// \since Crypto++ 8.1
+template <bool T_IsEncryption>
+class XChaCha20Poly1305_Final : public XChaCha20Poly1305_Base
+{
+public:
+	virtual ~XChaCha20Poly1305_Final() {}
+
+protected:
+	const SymmetricCipher & GetSymmetricCipher()
+		{return const_cast<XChaCha20Poly1305_Final *>(this)->AccessSymmetricCipher();}
+	SymmetricCipher & AccessSymmetricCipher()
+		{return m_cipher;}
+	bool IsForwardTransformation() const
+		{return T_IsEncryption;}
+
+	const MessageAuthenticationCode & GetMAC() const
+		{return const_cast<XChaCha20Poly1305_Final *>(this)->AccessMAC();}
+	MessageAuthenticationCode & AccessMAC()
+		{return m_mac;}
+
+private:
+	XChaCha20::Encryption m_cipher;
+	Poly1305TLS m_mac;
+};
+
+/// \brief IETF XChaCha20/Poly1305 AEAD scheme
+/// \details XChaCha20Poly1305 is an authenticated encryption scheme that combines
+///  XChaCha20 and Poly1305-TLS. The scheme is defined in RFC 8439, section 2.8,
+///  AEAD_XCHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
+///  and Poly1305.
+/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
+///  for IETF Protocols</A>.
+/// \since Crypto++ 8.1
+struct XChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation
+{
+	/// \brief XChaCha20Poly1305 encryption
+	typedef XChaCha20Poly1305_Final<true> Encryption;
+	/// \brief XChaCha20Poly1305 decryption
+	typedef XChaCha20Poly1305_Final<false> Decryption;
+};
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_CHACHA_POLY1305_H

+ 179 - 0
include/cryptlib/cham.h

@@ -0,0 +1,179 @@
+// cham.h - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton
+//          Based on "CHAM: A Family of Lightweight Block Ciphers for
+//          Resource-Constrained Devices" by Bonwook Koo, Dongyoung Roh,
+//          Hyeonjin Kim, Younghoon Jung, Dong-Geon Lee, and Daesung Kwon
+
+/// \file cham.h
+/// \brief Classes for the CHAM block cipher
+/// \since Crypto++ 8.0
+
+#ifndef CRYPTOPP_CHAM_H
+#define CRYPTOPP_CHAM_H
+
+#include "config.h"
+#include "seckey.h"
+#include "secblock.h"
+#include "algparam.h"
+
+#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86)
+# define CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS 1
+#endif
+
+// Yet another SunStudio/SunCC workaround. Failed self tests
+// in SSE code paths on i386 for SunStudio 12.3 and below.
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x5120)
+# undef CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief CHAM block cipher information
+/// \since Crypto++ 8.0
+struct CHAM64_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
+{
+    /// \brief The algorithm name
+    /// \return the algorithm name
+    /// \details StaticAlgorithmName returns the algorithm's name as a static
+    ///   member function.
+    static const std::string StaticAlgorithmName()
+    {
+        // Format is Cipher-Blocksize
+        return "CHAM-64";
+    }
+};
+
+/// \brief CHAM block cipher information
+/// \since Crypto++ 8.0
+struct CHAM128_Info : public FixedBlockSize<16>, public VariableKeyLength<16,16,32,16>
+{
+    /// \brief The algorithm name
+    /// \return the algorithm name
+    /// \details StaticAlgorithmName returns the algorithm's name as a static
+    ///   member function.
+    static const std::string StaticAlgorithmName()
+    {
+        // Format is Cipher-Blocksize
+        return "CHAM-128";
+    }
+};
+
+/// \brief CHAM 64-bit block cipher
+/// \details CHAM64 provides 64-bit block size. The valid key size is 128-bit.
+/// \note Crypto++ provides a byte oriented implementation
+/// \sa CHAM128, <a href="http://www.cryptopp.com/wiki/CHAM">CHAM</a>,
+///   <a href="https://pdfs.semanticscholar.org/2f57/61b5c2614cffd58a09cc83c375a2b32a2ed3.pdf">
+///   CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices</a>
+/// \since Crypto++ 8.0
+class CRYPTOPP_NO_VTABLE CHAM64 : public CHAM64_Info, public BlockCipherDocumentation
+{
+public:
+    /// \brief CHAM block cipher transformation functions
+    /// \details Provides implementation common to encryption and decryption
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<CHAM64_Info>
+    {
+    protected:
+        void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
+
+        SecBlock<word16> m_rk;
+        mutable FixedSizeSecBlock<word16, 4> m_x;
+        unsigned int m_kw;
+    };
+
+    /// \brief Encryption transformation
+    /// \details Enc provides implementation for encryption transformation. All key and block
+    ///   sizes are supported.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Enc : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+    };
+
+    /// \brief Decryption transformation
+    /// \details Dec provides implementation for decryption transformation. All key and block
+    ///   sizes are supported.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Dec : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+    };
+
+    /// \brief CHAM64 encryption
+    typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+    /// \brief CHAM64 decryption
+    typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+/// \brief CHAM64 encryption
+typedef CHAM64::Encryption CHAM64Encryption;
+/// \brief CHAM64 decryption
+typedef CHAM64::Decryption CHAM64Decryption;
+
+/// \brief CHAM 128-bit block cipher
+/// \details CHAM128 provides 128-bit block size. The valid key size is 128-bit and 256-bit.
+/// \note Crypto++ provides a byte oriented implementation
+/// \sa CHAM64, <a href="http://www.cryptopp.com/wiki/CHAM">CHAM</a>,
+///   <a href="https://pdfs.semanticscholar.org/2f57/61b5c2614cffd58a09cc83c375a2b32a2ed3.pdf">
+///   CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices</a>
+/// \since Crypto++ 8.0
+class CRYPTOPP_NO_VTABLE CHAM128 : public CHAM128_Info, public BlockCipherDocumentation
+{
+public:
+    /// \brief CHAM block cipher transformation functions
+    /// \details Provides implementation common to encryption and decryption
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<CHAM128_Info>
+    {
+    protected:
+        void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
+        std::string AlgorithmProvider() const;
+
+        SecBlock<word32> m_rk;
+        mutable FixedSizeSecBlock<word32, 4> m_x;
+        unsigned int m_kw;
+    };
+
+    /// \brief Encryption transformation
+    /// \details Enc provides implementation for encryption transformation. All key and block
+    ///   sizes are supported.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Enc : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
+        size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
+    };
+
+    /// \brief Decryption transformation
+    /// \details Dec provides implementation for decryption transformation. All key and block
+    ///   sizes are supported.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Dec : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
+        size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
+    };
+
+    /// \brief CHAM128 encryption
+    typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+    /// \brief CHAM128 decryption
+    typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+/// \brief CHAM128 encryption
+typedef CHAM128::Encryption CHAM128Encryption;
+/// \brief CHAM128 decryption
+typedef CHAM128::Decryption CHAM128Decryption;
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_CHAM_H

+ 10 - 0
include/cryptlib/cmac.h

@@ -10,6 +10,13 @@
 #include "seckey.h"
 #include "secblock.h"
 
+/// \brief Enable CMAC and wide block ciphers
+/// \details CMAC is only defined for AES. The library can support wide
+///  block ciphers like Kaylna and Threefish since we know the polynomials.
+#ifndef CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS
+# define CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS 1
+#endif  // CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS
+
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief CMAC base implementation
@@ -17,6 +24,8 @@ NAMESPACE_BEGIN(CryptoPP)
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
 {
 public:
+
+	virtual ~CMAC_Base() {}
 	CMAC_Base() : m_counter(0) {}
 
 	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
@@ -25,6 +34,7 @@ public:
 	unsigned int DigestSize() const {return GetCipher().BlockSize();}
 	unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();}
 	unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();}
+	std::string AlgorithmProvider() const {return GetCipher().AlgorithmProvider();}
 
 protected:
 	friend class EAX_Base;

+ 25 - 1164
include/cryptlib/config.h

@@ -1,1172 +1,33 @@
 // config.h - originally written and placed in the public domain by Wei Dai
 
+/// \file config.h
+/// \brief Library configuration file
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
 /// \file config.h
 /// \brief Library configuration file
 
 #ifndef CRYPTOPP_CONFIG_H
 #define CRYPTOPP_CONFIG_H
 
-// ***************** Important Settings ********************
-
-// define this if running on a big-endian CPU
-#if !defined(CRYPTOPP_LITTLE_ENDIAN) && !defined(CRYPTOPP_BIG_ENDIAN) && (defined(__BIG_ENDIAN__) || (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || (defined(__m68k__) || defined(__MC68K__)) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
-#	define CRYPTOPP_BIG_ENDIAN 1
-#endif
-
-// define this if running on a little-endian CPU
-// big endian will be assumed if CRYPTOPP_LITTLE_ENDIAN is not defined
-#if !defined(CRYPTOPP_BIG_ENDIAN) && !defined(CRYPTOPP_LITTLE_ENDIAN)
-#	define CRYPTOPP_LITTLE_ENDIAN 1
-#endif
-
-// Sanity checks. Some processors have more than big, little and bi-endian modes. PDP mode, where order results in "4312", should
-// raise red flags immediately. Additionally, mis-classified machines, like (previosuly) S/390, should raise red flags immediately.
-#if defined(CRYPTOPP_BIG_ENDIAN) && defined(__GNUC__) && defined(__BYTE_ORDER__) && (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__)
-# error "CRYPTOPP_BIG_ENDIAN is set, but __BYTE_ORDER__ is not __ORDER_BIG_ENDIAN__"
-#endif
-#if defined(CRYPTOPP_LITTLE_ENDIAN) && defined(__GNUC__) && defined(__BYTE_ORDER__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
-# error "CRYPTOPP_LITTLE_ENDIAN is set, but __BYTE_ORDER__ is not __ORDER_LITTLE_ENDIAN__"
-#endif
-
-// Define this if you want to disable all OS-dependent features,
-// such as sockets and OS-provided random number generators
-// #define NO_OS_DEPENDENCE
-
-// Define this to use features provided by Microsoft's CryptoAPI.
-// Currently the only feature used is Windows random number generation.
-// This macro will be ignored if NO_OS_DEPENDENCE is defined.
-// #define USE_MS_CRYPTOAPI
-
-// Define this to use features provided by Microsoft's CryptoNG API.
-// CryptoNG API is available in Vista and above and its cross platform,
-// including desktop apps and store apps. Currently the only feature
-// used is Windows random number generation.
-// This macro will be ignored if NO_OS_DEPENDENCE is defined.
-// #define USE_MS_CNGAPI
-
-// If the user did not make a choice, then select CryptoNG if
-// targeting Windows 8 or above.
-#if !defined(USE_MS_CRYPTOAPI) && !defined(USE_MS_CNGAPI)
-# if !defined(_USING_V110_SDK71_) && ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
-#  define USE_MS_CNGAPI
-# else
-#  define USE_MS_CRYPTOAPI
-# endif
-#endif
-
-// Define this to disable ASM, intrinsics and built-ins. The library will be
-// compiled using C++ only. The library code will not include SSE2 (and
-// above), NEON, Aarch32, Aarch64, Power4, Power7 or Power8. Note the compiler
-// may use higher ISAs depending on compiler options, but the library will not
-// explictly use the ISAs.
-// #define CRYPTOPP_DISABLE_ASM 1
-
-// Define CRYPTOPP_NO_CXX11 to avoid C++11 related features shown at the
-// end of this file. Some compilers and standard C++ headers advertise C++11
-// but they are really just C++03 with some additional C++11 headers and
-// non-conforming classes. You might also consider `-std=c++03` or
-// `-std=gnu++03`, but they are required options when building the library
-// and all programs. CRYPTOPP_NO_CXX11 is probably easier to manage but it may
-// cause -Wterminate warnings under GCC. MSVC++ has a similar warning.
-// Also see https://github.com/weidai11/cryptopp/issues/529
-// #define CRYPTOPP_NO_CXX11 1
-
-// Define CRYPTOPP_NO_CXX17 to avoid C++17 related features shown at the end of
-// this file. At the moment it should only affect std::uncaught_exceptions.
-// #define CRYPTOPP_NO_CXX17 1
-
-// Define this to allow unaligned data access. If you experience a break with
-// GCC at -O3, you should immediately suspect unaligned data accesses.
-// #define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS 1
-
-// ***************** Less Important Settings ***************
-
-// Library version macro. Since this macro is in a header, it reflects
-//   the version of the library the headers came from. It is not
-//   necessarily the version of the library built as a shared object if
-//   versions are inadvertently mixed and matched.
-#define CRYPTOPP_VERSION 700
-
-// Define this if you want to set a prefix for TestData/ and TestVectors/
-//   Be mindful of the trailing slash since its simple concatenation.
-//   g++ ... -DCRYPTOPP_DATA_DIR='"/tmp/cryptopp_test/share/"'
-#ifndef CRYPTOPP_DATA_DIR
-# define CRYPTOPP_DATA_DIR ""
-#endif
-
-// Define this if you want or need the library's memcpy_s and memmove_s.
-//   See http://github.com/weidai11/cryptopp/issues/28.
-// #if !defined(CRYPTOPP_WANT_SECURE_LIB)
-// # define CRYPTOPP_WANT_SECURE_LIB
-// #endif
-
-// File system code to write to GZIP archive.
-//   http://www.gzip.org/format.txt
-#if !defined(GZIP_OS_CODE)
-# if defined(__macintosh__)
-#  define GZIP_OS_CODE 7
-# elif defined(__unix__) || defined(__linux__)
-#  define GZIP_OS_CODE 3
-# else
-#  define GZIP_OS_CODE 0
-# endif
-#endif
-
-// Try this if your CPU has 256K internal cache or a slow multiply instruction
-// and you want a (possibly) faster IDEA implementation using log tables
-// #define IDEA_LARGECACHE
-
-// Define this if, for the linear congruential RNG, you want to use
-// the original constants as specified in S.K. Park and K.W. Miller's
-// CACM paper.
-// #define LCRNG_ORIGINAL_NUMBERS
-
-// Define this if you want Integer's operator<< to honor std::showbase (and
-// std::noshowbase). If defined, Integer will use a suffix of 'b', 'o', 'h'
-// or '.' (the last for decimal) when std::showbase is in effect. If
-// std::noshowbase is set, then the suffix is not added to the Integer. If
-// not defined, existing behavior is preserved and Integer will use a suffix
-// of 'b', 'o', 'h' or '.' (the last for decimal).
-// #define CRYPTOPP_USE_STD_SHOWBASE
-
-// Define this if ARMv8 shifts are slow. ARM Cortex-A53 and Cortex-A57 shift
-// operation perform poorly, so NEON and ASIMD code that relies on shifts
-// or rotates often performs worse than C/C++ code. Also see
-// http://github.com/weidai11/cryptopp/issues/367.
-#define CRYPTOPP_SLOW_ARMV8_SHIFT 1
-
-// Define this if you want to decouple AlgorithmParameters and Integer
-// The decoupling should make it easier for the linker to remove Integer
-// related code for those who do not need Integer, and avoid a potential
-// race during AssignIntToInteger pointer initialization. Also
-// see http://github.com/weidai11/cryptopp/issues/389.
-// #define CRYPTOPP_NO_ASSIGN_TO_INTEGER
-
-// choose which style of sockets to wrap (mostly useful for MinGW which has both)
-#if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS)
-# define PREFER_BERKELEY_STYLE_SOCKETS
-#endif
-
-// #if !defined(NO_WINDOWS_STYLE_SOCKETS) && !defined(PREFER_WINDOWS_STYLE_SOCKETS)
-// # define PREFER_WINDOWS_STYLE_SOCKETS
-// #endif
-
-// set the name of Rijndael cipher, was "Rijndael" before version 5.3
-#define CRYPTOPP_RIJNDAEL_NAME "AES"
-
-// CRYPTOPP_DEBUG enables the library's CRYPTOPP_ASSERT. CRYPTOPP_ASSERT
-//   raises a SIGTRAP (Unix) or calls DebugBreak() (Windows). CRYPTOPP_ASSERT
-//   is only in effect when CRYPTOPP_DEBUG, DEBUG or _DEBUG is defined. Unlike
-//   Posix assert, CRYPTOPP_ASSERT is not affected by NDEBUG (or failure to
-//   define it).
-//   Also see http://github.com/weidai11/cryptopp/issues/277, CVE-2016-7420
-#if (defined(DEBUG) || defined(_DEBUG)) && !defined(CRYPTOPP_DEBUG)
-# define CRYPTOPP_DEBUG 1
-#endif
-
-// ***************** Important Settings Again ********************
-// But the defaults should be ok.
-
-// namespace support is now required
-#ifdef NO_NAMESPACE
-#	error namespace support is now required
-#endif
-
-#ifdef CRYPTOPP_DOXYGEN_PROCESSING
-// Document the namespce exists. Put it here before CryptoPP is undefined below.
-/// \namespace CryptoPP
-/// \brief Crypto++ library namespace
-/// \details Nearly all classes are located in the CryptoPP namespace. Within
-///   the namespace, there are two additional namespaces.
-///   <ul>
-///     <li>Name - namespace for names used with \p NameValuePairs and documented in argnames.h
-///     <li>NaCl - namespace for NaCl library functions like crypto_box, crypto_box_open, crypto_sign, and crypto_sign_open
-///     <li>Test - namespace for testing and benchmarks classes
-///     <li>Weak - namespace for weak and wounded algorithms, like ARC4, MD5 and Pananma
-///   </ul>
-namespace CryptoPP { }
-// Bring in the symbols found in the weak namespace; and fold Weak1 into Weak
-#		define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
-#		define Weak1 Weak
-// Avoid putting "CryptoPP::" in front of everything in Doxygen output
-#       define CryptoPP
-#       define NAMESPACE_BEGIN(x)
-#       define NAMESPACE_END
-// Get Doxygen to generate better documentation for these typedefs
-#       define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
-// Make "protected" "private" so the functions and members are not documented
-#		define protected private
-#else
-#       define NAMESPACE_BEGIN(x) namespace x {
-#       define NAMESPACE_END }
-#       define DOCUMENTED_TYPEDEF(x, y) typedef x y;
-#endif
-#define ANONYMOUS_NAMESPACE_BEGIN namespace {
-#define ANONYMOUS_NAMESPACE_END }
-#define USING_NAMESPACE(x) using namespace x;
-#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
-#define DOCUMENTED_NAMESPACE_END }
-
-// What is the type of the third parameter to bind?
-// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
-// Unfortunately there is no way to tell whether or not socklen_t is defined.
-// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
-#ifndef TYPE_OF_SOCKLEN_T
-#	if defined(_WIN32) || defined(__CYGWIN__)
-#		define TYPE_OF_SOCKLEN_T int
-#	else
-#		define TYPE_OF_SOCKLEN_T ::socklen_t
-#	endif
-#endif
-
-#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
-#	define __USE_W32_SOCKETS
-#endif
-
-// Originally in global namespace to avoid ambiguity with other byte typedefs.
-// Moved to Crypto++ namespace due to C++17, std::byte and potential compile problems. Also see
-// http://www.cryptopp.com/wiki/std::byte and http://github.com/weidai11/cryptopp/issues/442
-// typedef unsigned char byte;
-#define CRYPTOPP_NO_GLOBAL_BYTE 1
-
-NAMESPACE_BEGIN(CryptoPP)
-
-// Signed words added at Issue 609 for early versions of and Visual Studio and
-//   the NaCl gear.  Also see https://github.com/weidai11/cryptopp/issues/609.
-
-typedef unsigned char byte;
-typedef unsigned short word16;
-typedef unsigned int word32;
-
-typedef signed char sbyte;
-typedef signed short sword16;
-typedef signed int sword32;
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-	typedef signed __int64 sword64;
-	typedef unsigned __int64 word64;
-	#define SW64LIT(x) x##i64
-	#define W64LIT(x) x##ui64
-#elif (_LP64 || __LP64__)
-	typedef signed long sword64;
-	typedef unsigned long word64;
-	#define SW64LIT(x) x##L
-	#define W64LIT(x) x##UL
-#else
-	typedef signed long long sword64;
-	typedef unsigned long long word64;
-	#define SW64LIT(x) x##LL
-	#define W64LIT(x) x##ULL
-#endif
-
-// define large word type, used for file offsets and such
-typedef word64 lword;
-const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
-
-// Clang pretends to be VC++, too.
-//   See http://github.com/weidai11/cryptopp/issues/147
-#if defined(_MSC_VER) && defined(__clang__)
-# error: "Unsupported configuration"
-#endif
-
-#ifdef __GNUC__
-	#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-#endif
-
-#if defined(__xlc__) || defined(__xlC__)
-	#define CRYPTOPP_XLC_VERSION ((__xlC__ / 256) * 10000 + (__xlC__ % 256) * 100)
-#endif
-
-// Apple and LLVM's Clang. Apple Clang version 7.0 roughly equals LLVM Clang version 3.7
-#if defined(__clang__) && defined(__apple_build_version__)
-	#define CRYPTOPP_APPLE_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
-	#define CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER 1
-#elif defined(__clang__)
-	#define CRYPTOPP_LLVM_CLANG_VERSION  (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
-	#define CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER 1
-#endif
-
-#ifdef _MSC_VER
-	#define CRYPTOPP_MSC_VERSION (_MSC_VER)
-#endif
-
-// Need GCC 4.6/Clang 1.7/Apple Clang 2.0 or above due to "GCC diagnostic {push|pop}"
-#if (CRYPTOPP_GCC_VERSION >= 40600) || (CRYPTOPP_LLVM_CLANG_VERSION >= 10700) || (CRYPTOPP_APPLE_CLANG_VERSION >= 20000)
-	#define CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE 1
-#endif
-
-// Clang due to "Inline assembly operands don't work with .intel_syntax", http://llvm.org/bugs/show_bug.cgi?id=24232. Still broke as of Clang 3.9.
-//   TODO: supply the upper version when LLVM fixes it. We set it to 20.0 for compilation purposes.
-#if (defined(CRYPTOPP_LLVM_CLANG_VERSION) && (CRYPTOPP_LLVM_CLANG_VERSION <= 200000)) || \
-	(defined(CRYPTOPP_APPLE_CLANG_VERSION) && (CRYPTOPP_APPLE_CLANG_VERSION <= 200000)) || \
-	defined(CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER)
-	#define CRYPTOPP_DISABLE_INTEL_ASM 1
-#endif
-
-// define hword, word, and dword. these are used for multiprecision integer arithmetic
-// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
-#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
-	typedef word32 hword;
-	typedef word64 word;
-#else
-	#define CRYPTOPP_NATIVE_DWORD_AVAILABLE 1
-	#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
-		#if ((CRYPTOPP_GCC_VERSION >= 30400) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30000) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300)) && (__SIZEOF_INT128__ >= 16)
-			// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
-			// GCC 4.8.3 and bad uint128_t ops on PPC64/POWER7 (Issue 421)
-			// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
-			typedef word32 hword;
-			typedef word64 word;
-			typedef __uint128_t dword;
-			typedef __uint128_t word128;
-			#define CRYPTOPP_WORD128_AVAILABLE 1
-		#else
-			// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
-			typedef word16 hword;
-			typedef word32 word;
-			typedef word64 dword;
-		#endif
-	#else
-		// being here means the native register size is probably 32 bits or less
-		#define CRYPTOPP_BOOL_SLOW_WORD64 1
-		typedef word16 hword;
-		typedef word32 word;
-		typedef word64 dword;
-	#endif
-#endif
-#ifndef CRYPTOPP_BOOL_SLOW_WORD64
-	#define CRYPTOPP_BOOL_SLOW_WORD64 0
-#endif
-
-const unsigned int WORD_SIZE = sizeof(word);
-const unsigned int WORD_BITS = WORD_SIZE * 8;
-
-NAMESPACE_END
-
-#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
-	// This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
-	// Also see http://stackoverflow.com/questions/794632/programmatically-get-the-cache-line-size.
-	#if defined(_M_X64) || defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__) || defined(__powerpc64__) || defined(_ARCH_PPC64)
-		#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
-	#else
-		// L1 cache line size is 32 on Pentium III and earlier
-		#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
-	#endif
-#endif
-
-#ifndef CRYPTOPP_ALIGN_DATA
-	#if defined(_MSC_VER)
-		#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
-	#elif defined(__GNUC__)
-		#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
-	#else
-		#define CRYPTOPP_ALIGN_DATA(x)
-	#endif
-#endif
-
-// The section attribute attempts to initialize CPU flags to avoid Valgrind findings above -O1
-#if ((defined(__MACH__) && defined(__APPLE__)) && ((CRYPTOPP_LLVM_CLANG_VERSION >= 30600) || (CRYPTOPP_APPLE_CLANG_VERSION >= 70100) || (CRYPTOPP_GCC_VERSION >= 40300)))
-	#define CRYPTOPP_SECTION_INIT __attribute__((section ("__DATA,__data")))
-#elif (defined(__ELF__) && (CRYPTOPP_GCC_VERSION >= 40300))
-	#define CRYPTOPP_SECTION_INIT __attribute__((section ("nocommon")))
-#else
-	#define CRYPTOPP_SECTION_INIT
-#endif
-
-#if defined(_MSC_VER) || defined(__fastcall)
-	#define CRYPTOPP_FASTCALL __fastcall
-#else
-	#define CRYPTOPP_FASTCALL
-#endif
-
-#ifdef _MSC_VER
-#define CRYPTOPP_NO_VTABLE __declspec(novtable)
-#else
-#define CRYPTOPP_NO_VTABLE
-#endif
-
-#ifdef _MSC_VER
-	// 4127: conditional expression is constant
-	// 4231: nonstandard extension used : 'extern' before template explicit instantiation
-	// 4250: dominance
-	// 4251: member needs to have dll-interface
-	// 4275: base needs to have dll-interface
-	// 4505: unreferenced local function
-	// 4512: assignment operator not generated
-	// 4660: explicitly instantiating a class that's already implicitly instantiated
-	// 4661: no suitable definition provided for explicit template instantiation request
-	// 4786: identifier was truncated in debug information
-	// 4355: 'this' : used in base member initializer list
-	// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
-#	pragma warning(disable: 4127 4512 4661 4910)
-	// Security related, possible defects
-	// http://blogs.msdn.com/b/vcblog/archive/2010/12/14/off-by-default-compiler-warnings-in-visual-c.aspx
-#	pragma warning(once: 4191 4242 4263 4264 4266 4302 4826 4905 4906 4928)
-#endif
-
-#ifdef __BORLANDC__
-// 8037: non-const function called for const object. needed to work around BCB2006 bug
-#	pragma warn -8037
-#endif
-
-// [GCC Bug 53431] "C++ preprocessor ignores #pragma GCC diagnostic". Clang honors it.
-#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
-# pragma GCC diagnostic ignored "-Wunknown-pragmas"
-# pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-// You may need to force include a C++ header on Android when using STLPort to ensure
-// _STLPORT_VERSION is defined: CXXFLAGS="-DNDEBUG -g2 -O2 -std=c++11 -include iosfwd"
-// TODO: Figure out C++17 and lack of std::uncaught_exception
-#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || (defined(_STLPORT_VERSION) && ((_STLPORT_VERSION < 0x450) || defined(_STLP_NO_UNCAUGHT_EXCEPT_SUPPORT)))
-#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
-#endif
-
-#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
-#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
-#endif
-
-// ***************** Platform and CPU features ********************
-
-// Linux provides X32, which is 32-bit integers, longs and pointers on x86_64 using the full x86_64 register set.
-// Detect via __ILP32__ (http://wiki.debian.org/X32Port). However, __ILP32__ shows up in more places than
-// the System V ABI specs calls out, like on some Solaris installations and just about any 32-bit system with Clang.
-#if (defined(__ILP32__) || defined(_ILP32)) && defined(__x86_64__)
-	#define CRYPTOPP_BOOL_X32 1
-#endif
-
-// see http://predef.sourceforge.net/prearch.html
-#if (defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)) && !CRYPTOPP_BOOL_X32
-	#define CRYPTOPP_BOOL_X86 1
-#endif
-
-#if (defined(_M_X64) || defined(__x86_64__)) && !CRYPTOPP_BOOL_X32
-	#define CRYPTOPP_BOOL_X64 1
-#endif
-
-// Undo the ASM and Intrinsic related defines due to X32.
-#if CRYPTOPP_BOOL_X32
-# undef CRYPTOPP_BOOL_X64
-# undef CRYPTOPP_X64_ASM_AVAILABLE
-# undef CRYPTOPP_X64_MASM_AVAILABLE
-#endif
-
-// Microsoft plans to support ARM-64, but its not clear how to detect it.
-//   TODO: Add MSC_VER and ARM-64 platform define when available
-#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
-	#define CRYPTOPP_BOOL_ARM64 1
-#elif defined(__arm__) || defined(__aarch32__) || defined(_M_ARM)
-	#define CRYPTOPP_BOOL_ARM32 1
-#endif
-
-// AltiVec and Power8 crypto
-#if defined(__powerpc64__) || defined(_ARCH_PPC64)
-	#define CRYPTOPP_BOOL_PPC64 1
-#elif defined(__powerpc__) || defined(_ARCH_PPC)
-	#define CRYPTOPP_BOOL_PPC32 1
-#endif
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-# define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 1
-#else
-# define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY 1
-#endif
-
-// ***************** IA32 CPU features ********************
-
-#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
-
-// Apple Clang prior to 5.0 cannot handle SSE2
-#if defined(CRYPTOPP_APPLE_CLANG_VERSION) && (CRYPTOPP_APPLE_CLANG_VERSION < 50000)
-# define CRYPTOPP_DISABLE_ASM
-#endif
-
-// Sun Studio 12 provides GCC inline assembly, http://blogs.oracle.com/x86be/entry/gcc_style_asm_inlining_support
-// We can enable SSE2 for Sun Studio in the makefile with -D__SSE2__, but users may not compile with it.
-#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(__SSE2__) && defined(__x86_64__) && (__SUNPRO_CC >= 0x5100)
-# define __SSE2__ 1
-#endif
-
-#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
-	// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
-	#define CRYPTOPP_X86_ASM_AVAILABLE 1
-
-	#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(_MSC_VER) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__))
-		#define CRYPTOPP_SSE2_ASM_AVAILABLE 1
-	#endif
-
-	#if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1500 || defined(__SSSE3__))
-		#define CRYPTOPP_SSSE3_ASM_AVAILABLE 1
-	#endif
-#endif
-
-#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
-	#define CRYPTOPP_X64_MASM_AVAILABLE 1
-#endif
-
-#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
-	#define CRYPTOPP_X64_ASM_AVAILABLE 1
-#endif
-
-// 32-bit SunCC does not enable SSE2 by default.
-#if !defined(CRYPTOPP_DISABLE_ASM) && (defined(_MSC_VER) || defined(__SSE2__))
-	#define CRYPTOPP_SSE2_INTRIN_AVAILABLE 1
-#endif
-
-#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_SSSE3)
-# if defined(__SSSE3__) || (_MSC_VER >= 1500) || \
-	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || (__SUNPRO_CC >= 0x5110) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000)
-	#define CRYPTOPP_SSSE3_AVAILABLE 1
-# endif
-#endif
-
-// Intrinsics availible in GCC 4.3 (http://gcc.gnu.org/gcc-4.3/changes.html) and
-//   MSVC 2008 (http://msdn.microsoft.com/en-us/library/bb892950%28v=vs.90%29.aspx)
-//   SunCC could generate SSE4 at 12.1, but the intrinsics are missing until 12.4.
-#if !defined(CRYPTOPP_DISABLE_SSE4) && defined(CRYPTOPP_SSSE3_AVAILABLE) && \
-	(defined(__SSE4_1__) || (CRYPTOPP_MSC_VERSION >= 1500) || \
-	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || (__SUNPRO_CC >= 0x5110) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000))
-	#define CRYPTOPP_SSE41_AVAILABLE 1
-#endif
-
-#if !defined(CRYPTOPP_DISABLE_SSE4) && defined(CRYPTOPP_SSSE3_AVAILABLE) && \
-	(defined(__SSE4_2__) || (CRYPTOPP_MSC_VERSION >= 1500) || (__SUNPRO_CC >= 0x5110) || \
-	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000))
-	#define CRYPTOPP_SSE42_AVAILABLE 1
-#endif
-
-// Couple to CRYPTOPP_DISABLE_AES, but use CRYPTOPP_CLMUL_AVAILABLE so we can selectively
-//  disable for misbehaving platofrms and compilers, like Solaris or some Clang.
-#if defined(CRYPTOPP_DISABLE_AES)
-	#define CRYPTOPP_DISABLE_CLMUL 1
-#endif
-
-// Requires Sun Studio 12.3 (SunCC 0x5120) in theory.
-#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_CLMUL) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
-	(defined(__PCLMUL__) || (_MSC_FULL_VER >= 150030729) || (__SUNPRO_CC >= 0x5120) || \
-	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1110) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 30200) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300))
-	#define CRYPTOPP_CLMUL_AVAILABLE 1
-#endif
-
-// Requires Sun Studio 12.3 (SunCC 0x5120)
-#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_AES) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
-	(defined(__AES__) || (_MSC_FULL_VER >= 150030729) || (__SUNPRO_CC >= 0x5120) || \
-	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1110) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 30200) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300))
-	#define CRYPTOPP_AESNI_AVAILABLE 1
-#endif
-
-// Guessing at SHA for SunCC. Its not in Sun Studio 12.6. Also see
-//   http://stackoverflow.com/questions/45872180/which-xarch-for-sha-extensions-on-solaris
-#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_SHA) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
-	(defined(__SHA__) || (CRYPTOPP_MSC_VERSION >= 1900) || (__SUNPRO_CC >= 0x5160) || \
-	(CRYPTOPP_GCC_VERSION >= 40900) || (__INTEL_COMPILER >= 1300) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 30400) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50100))
-	#define CRYPTOPP_SHANI_AVAILABLE 1
-#endif
-
-#endif  // X86, X32, X64
-
-// ***************** ARM CPU features ********************
-
-#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
-
-// Requires ARMv7 and ACLE 1.0. Testing shows ARMv7 is really ARMv7a under most toolchains.
-// Android still uses ARMv5 and ARMv6 so we have to be conservative when enabling NEON.
-#if !defined(CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
-# if defined(__ARM_NEON) || defined(__ARM_NEON_FP) || defined(__ARM_FEATURE_NEON) || \
-	(__ARM_ARCH >= 7) || (CRYPTOPP_MSC_VERSION >= 1700)
-#  define CRYPTOPP_ARM_NEON_AVAILABLE 1
-# endif
-#endif
-
-// ARMv8 and ASIMD, which is NEON. It is part of ARMv8 core.
-// TODO: Add MSC_VER and ARM-64 platform define when available
-#if !defined(CRYPTOPP_ARM_ASIMD_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
-# if defined(__aarch32__) || defined(__aarch64__) || (CRYPTOPP_MSC_VERSION >= 1910)
-#  define CRYPTOPP_ARM_ASIMD_AVAILABLE 1
-# endif
-#endif
-
-// Requires ARMv8 and ACLE 2.0. GCC requires 4.8 and above.
-// LLVM Clang requires 3.5. Apple Clang is unknown at the moment.
-// Microsoft plans to support ARM-64, but its not clear how to detect it.
-// TODO: Add Android ARMv8 support for CRC32
-// TODO: Add MSC_VER and ARM-64 platform define when available
-#if !defined(CRYPTOPP_ARM_CRC32_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) && !defined(__apple_build_version__) && !defined(__ANDROID__)
-# if (defined(__ARM_FEATURE_CRC32) || (CRYPTOPP_MSC_VERSION >= 1910) || \
-	defined(__aarch32__) || defined(__aarch64__))
-#  define CRYPTOPP_ARM_CRC32_AVAILABLE 1
-# endif
-#endif
-
-// Requires ARMv8 and ACLE 2.0. GCC requires 4.8 and above.
-// LLVM Clang requires 3.5. Apple Clang is unknown at the moment.
-// Microsoft plans to support ARM-64, but its not clear how to detect it.
-// TODO: Add Android ARMv8 support for PMULL
-// TODO: Add MSC_VER and ARM-64 platform define when available
-#if !defined(CRYPTOPP_ARM_PMULL_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) && !defined(__apple_build_version__) && !defined(__ANDROID__)
-# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_MSC_VERSION >= 1910) || \
-	defined(__aarch32__) || defined(__aarch64__)
-#  define CRYPTOPP_ARM_PMULL_AVAILABLE 1
-# endif
-#endif
-
-// Requires ARMv8 and ACLE 2.0. GCC requires 4.8 and above.
-// LLVM Clang requires 3.5. Apple Clang is unknown at the moment.
-// Microsoft plans to support ARM-64, but its not clear how to detect it.
-// TODO: Add Android ARMv8 support for AES and SHA
-// TODO: Add MSC_VER and ARM-64 platform define when available
-#if !defined(CRYPTOPP_ARM_AES_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) && !defined(__ANDROID__)
-# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_MSC_VERSION >= 1910) || \
-	defined(__aarch32__) || defined(__aarch64__)
-#  define CRYPTOPP_ARM_AES_AVAILABLE 1
-# endif
-#endif
-
-// Requires ARMv8 and ACLE 2.0. GCC requires 4.8 and above.
-// LLVM Clang requires 3.5. Apple Clang is unknown at the moment.
-// Microsoft plans to support ARM-64, but its not clear how to detect it.
-// TODO: Add Android ARMv8 support for AES and SHA
-// TODO: Add MSC_VER and ARM-64 platform define when available
-#if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) && !defined(__ANDROID__)
-# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_MSC_VERSION >= 1910) || \
-	defined(__aarch32__) || defined(__aarch64__)
-#  define CRYPTOPP_ARM_SHA_AVAILABLE 1
-# endif
-#endif
-
-// Limit the <arm_acle.h> include.
-#if defined(__aarch32__) || defined(__aarch64__) || (__ARM_ARCH >= 8) || defined(__ARM_ACLE)
-# define CRYPTOPP_ARM_ACLE_AVAILABLE 1
-#endif
-
-// Man, this is borked. Apple Clang defines __ARM_ACLE but then fails
-// to compile with "fatal error: 'arm_acle.h' file not found"
-#if defined(__ANDROID__) || defined(ANDROID) || defined(__APPLE__)
-# undef CRYPTOPP_ARM_ACLE_AVAILABLE
-#endif
-
-#endif  // ARM32, ARM64
-
-// ***************** AltiVec and Power8 ********************
-
-#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
-
-#if defined(CRYPTOPP_DISABLE_ALTIVEC) || defined(CRYPTOPP_DISABLE_ASM)
-# undef CRYPTOPP_DISABLE_ALTIVEC
-# undef CRYPTOPP_DISABLE_POWER7
-# undef CRYPTOPP_DISABLE_POWER8
-# define CRYPTOPP_DISABLE_ALTIVEC 1
-# define CRYPTOPP_DISABLE_POWER7 1
-# define CRYPTOPP_DISABLE_POWER8 1
-#endif
-
-// An old Apple G5 with GCC 4.01 has AltiVec, but its only Power4 or so.
-#if !defined(CRYPTOPP_ALTIVEC_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ALTIVEC)
-# if defined(_ARCH_PWR4) || defined(__ALTIVEC__) || \
-	(CRYPTOPP_XLC_VERSION >= 100000) || (CRYPTOPP_GCC_VERSION >= 40001)
-#  define CRYPTOPP_ALTIVEC_AVAILABLE 1
-# endif
-#endif
-
-// We need Power5 for 'vector unsigned long long'
-#if !defined(CRYPTOPP_POWER5_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER5) && defined(CRYPTOPP_ALTIVEC_AVAILABLE)
-# if defined(_ARCH_PWR5) || (CRYPTOPP_XLC_VERSION >= 100000) || (CRYPTOPP_GCC_VERSION >= 40100)
-#  define CRYPTOPP_POWER5_AVAILABLE 1
-# endif
-#endif
-
-// We need Power7 for unaligned loads and stores
-#if !defined(CRYPTOPP_POWER7_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER7) && defined(CRYPTOPP_ALTIVEC_AVAILABLE)
-# if defined(_ARCH_PWR7) || (CRYPTOPP_XLC_VERSION >= 100000) || (CRYPTOPP_GCC_VERSION >= 40100)
-#  define CRYPTOPP_POWER7_AVAILABLE 1
-# endif
-#endif
-
-// We need Power8 for in-core crypto
-#if !defined(CRYPTOPP_POWER8_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER8) && defined(CRYPTOPP_POWER7_AVAILABLE)
-# if defined(_ARCH_PWR8) || (CRYPTOPP_XLC_VERSION >= 130000) || (CRYPTOPP_GCC_VERSION >= 40800)
-#  define CRYPTOPP_POWER8_AVAILABLE 1
-# endif
-#endif
-
-#if !defined(CRYPTOPP_POWER8_AES_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER8_AES) && defined(CRYPTOPP_POWER8_AVAILABLE)
-# if defined(__CRYPTO__) || defined(_ARCH_PWR8) || (CRYPTOPP_XLC_VERSION >= 130000) || (CRYPTOPP_GCC_VERSION >= 40800)
-#  define CRYPTOPP_POWER8_AES_AVAILABLE 1
-#  define CRYPTOPP_POWER8_SHA_AVAILABLE 1
-//#  define CRYPTOPP_POWER8_CRC_AVAILABLE 1
-# endif
-#endif
-
-#endif  // PPC, PPC64
-
-// ***************** Miscellaneous ********************
-
-// Nearly all Intel's and AMD's have SSE. Enable it independent of SSE ASM and intrinscs
-#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) && !defined(CRYPTOPP_DISABLE_ASM)
-	#define CRYPTOPP_BOOL_ALIGN16 1
-#else
-	#define CRYPTOPP_BOOL_ALIGN16 0
-#endif
-
-// How to allocate 16-byte aligned memory (for SSE2)
-// posix_memalign see https://forum.kde.org/viewtopic.php?p=66274
-#if defined(_MSC_VER)
-	#define CRYPTOPP_MM_MALLOC_AVAILABLE
-#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
-	#define CRYPTOPP_MEMALIGN_AVAILABLE
-#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-	#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
-#elif (defined(_GNU_SOURCE) || ((_XOPEN_SOURCE + 0) >= 600)) && (_POSIX_ADVISORY_INFO > 0)
-	#define CRYPTOPP_POSIX_MEMALIGN_AVAILABLE
-#else
-	#define CRYPTOPP_NO_ALIGNED_ALLOC
-#endif
-
-// how to disable inlining
-#if defined(_MSC_VER)
-#	define CRYPTOPP_NOINLINE_DOTDOTDOT
-#	define CRYPTOPP_NOINLINE __declspec(noinline)
-#elif defined(__xlc__) || defined(__xlC__)
-#	define CRYPTOPP_NOINLINE_DOTDOTDOT ...
-#	define CRYPTOPP_NOINLINE __attribute__((noinline))
-#elif defined(__GNUC__)
-#	define CRYPTOPP_NOINLINE_DOTDOTDOT
-#	define CRYPTOPP_NOINLINE __attribute__((noinline))
-#else
-#	define CRYPTOPP_NOINLINE_DOTDOTDOT ...
-#	define CRYPTOPP_NOINLINE
-#endif
-
-// How to declare class constants
-#if defined(CRYPTOPP_DOXYGEN_PROCESSING) || defined(__BORLANDC__)
-# define CRYPTOPP_CONSTANT(x) static const int x;
-#else
-# define CRYPTOPP_CONSTANT(x) enum {x};
-#endif
-
-// How to disable CPU feature probing. We determine machine
-//  capabilities by performing an os/platform *query* first,
-//  like getauxv(). If the *query* fails, we move onto a
-//  cpu *probe*. The cpu *probe* tries to exeute an instruction
-//  and then catches a SIGILL on Linux or the exception
-//  EXCEPTION_ILLEGAL_INSTRUCTION on Windows. Some OSes
-//  fail to hangle a SIGILL gracefully, like Apple OSes. Apple
-//  machines corrupt memory and variables around the probe.
-#if defined(__APPLE__)
-#  define CRYPTOPP_NO_CPU_FEATURE_PROBES 1
-#endif
-
-// ***************** Initialization and Constructor priorities ********************
-
-// CRYPTOPP_INIT_PRIORITY attempts to manage initialization of C++ static objects.
-// Under GCC, the library uses init_priority attribute in the range
-// [CRYPTOPP_INIT_PRIORITY, CRYPTOPP_INIT_PRIORITY+100]. Under Windows,
-// CRYPTOPP_INIT_PRIORITY enlists "#pragma init_seg(lib)". The platforms
-// with gaps are Apple and Sun because they require linker scripts. Apple and
-// Sun will use the library's Singletons to initialize and acquire resources.
-// Also see http://cryptopp.com/wiki/Static_Initialization_Order_Fiasco
-#ifndef CRYPTOPP_INIT_PRIORITY
-# define CRYPTOPP_INIT_PRIORITY 250
-#endif
-
-// CRYPTOPP_USER_PRIORITY is for other libraries and user code that is using Crypto++
-// and managing C++ static object creation. It is guaranteed not to conflict with
-// values used by (or would be used by) the Crypto++ library.
-#if defined(CRYPTOPP_INIT_PRIORITY) && (CRYPTOPP_INIT_PRIORITY > 0)
-# define CRYPTOPP_USER_PRIORITY (CRYPTOPP_INIT_PRIORITY + 101)
-#else
-# define CRYPTOPP_USER_PRIORITY 350
-#endif
-
-// Most platforms allow us to specify when to create C++ objects. Apple and Sun do not.
-#if (CRYPTOPP_INIT_PRIORITY > 0) && !(defined(NO_OS_DEPENDENCE) || defined(__APPLE__) || defined(__sun__))
-# if (CRYPTOPP_GCC_VERSION >= 30000) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (_INTEL_COMPILER >= 800)
-#  define HAVE_GCC_INIT_PRIORITY 1
-# elif (CRYPTOPP_MSC_VERSION >= 1310)
-#  define HAVE_MSC_INIT_PRIORITY 1
-# endif
-#endif  // CRYPTOPP_INIT_PRIORITY, NO_OS_DEPENDENCE, Apple, Sun
-
-// ***************** determine availability of OS features ********************
-
-#ifndef NO_OS_DEPENDENCE
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-#define CRYPTOPP_WIN32_AVAILABLE
-#endif
-
-#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
-#define CRYPTOPP_UNIX_AVAILABLE
-#endif
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-#define CRYPTOPP_BSD_AVAILABLE
-#endif
-
-#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
-#	define HIGHRES_TIMER_AVAILABLE
-#endif
-
-#ifdef CRYPTOPP_WIN32_AVAILABLE
-# if !defined(WINAPI_FAMILY)
-#	define THREAD_TIMER_AVAILABLE
-# elif defined(WINAPI_FAMILY)
-#   if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
-#	  define THREAD_TIMER_AVAILABLE
-#  endif
-# endif
-#endif
-
-#ifdef CRYPTOPP_UNIX_AVAILABLE
-#	define HAS_BERKELEY_STYLE_SOCKETS
-#	define SOCKETS_AVAILABLE
-#endif
-
-// Sockets are only available under Windows Runtime desktop partition apps (despite the MSDN literature)
-#ifdef CRYPTOPP_WIN32_AVAILABLE
-# define HAS_WINDOWS_STYLE_SOCKETS
-# if !defined(WINAPI_FAMILY)
-#	define SOCKETS_AVAILABLE
-# elif defined(WINAPI_FAMILY)
-#   if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
-#	  define SOCKETS_AVAILABLE
-#   endif
-# endif
-#endif
-
-#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
-#	define USE_WINDOWS_STYLE_SOCKETS
-#else
-#	define USE_BERKELEY_STYLE_SOCKETS
-#endif
-
-#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(SOCKETS_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
-#	define WINDOWS_PIPES_AVAILABLE
-#endif
-
-
-#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
-#	define NONBLOCKING_RNG_AVAILABLE
-#	define BLOCKING_RNG_AVAILABLE
-#	define OS_RNG_AVAILABLE
-#	define HAS_PTHREADS
-#	define THREADS_AVAILABLE
-#endif
-
-// Early IBM XL C on AIX fails to link due to missing pthread gear
-#if defined(_AIX) && defined(__xlC__)
-#	undef HAS_PTHREADS
-#	undef THREADS_AVAILABLE
-#endif
-
-// Cygwin/Newlib requires _XOPEN_SOURCE=600
-#if defined(CRYPTOPP_UNIX_AVAILABLE)
-# define UNIX_SIGNALS_AVAILABLE 1
-#endif
-
-#ifdef CRYPTOPP_WIN32_AVAILABLE
-# if !defined(WINAPI_FAMILY)
-#	define HAS_WINTHREADS
-#	define THREADS_AVAILABLE
-#	define NONBLOCKING_RNG_AVAILABLE
-#	define OS_RNG_AVAILABLE
-# elif defined(WINAPI_FAMILY)
-#   if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
-#	  define HAS_WINTHREADS
-#	  define THREADS_AVAILABLE
-#	  define NONBLOCKING_RNG_AVAILABLE
-#	  define OS_RNG_AVAILABLE
-#   elif !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
-#     if ((WINVER >= 0x0A00 /*_WIN32_WINNT_WIN10*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/))
-#	    define NONBLOCKING_RNG_AVAILABLE
-#	    define OS_RNG_AVAILABLE
-#     endif
-#   endif
-# endif
-#endif
-
-#endif	// NO_OS_DEPENDENCE
-
-// ***************** DLL related ********************
-
-#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
-
-#ifdef CRYPTOPP_EXPORTS
-#define CRYPTOPP_IS_DLL
-#define CRYPTOPP_DLL __declspec(dllexport)
-#elif defined(CRYPTOPP_IMPORTS)
-#define CRYPTOPP_IS_DLL
-#define CRYPTOPP_DLL __declspec(dllimport)
-#else
-#define CRYPTOPP_DLL
-#endif
-
-// C++ makes const internal linkage
-#define CRYPTOPP_TABLE extern
-#define CRYPTOPP_API __cdecl
-
-#else	// not CRYPTOPP_WIN32_AVAILABLE
-
-// C++ makes const internal linkage
-#define CRYPTOPP_TABLE extern
-#define CRYPTOPP_DLL
-#define CRYPTOPP_API
-
-#endif	// CRYPTOPP_WIN32_AVAILABLE
-
-#if defined(__MWERKS__)
-#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
-#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
-#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
-#else
-#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
-#endif
-
-#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
-#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
-#else
-#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
-#endif
-
-#if defined(__MWERKS__)
-#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
-#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
-#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
-#else
-#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
-#endif
-
-#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
-#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
-#else
-#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
-#endif
-
-// ************** Unused variable ***************
-
-// Portable way to suppress warnings.
-//   Moved from misc.h due to circular depenedencies.
-#define CRYPTOPP_UNUSED(x) ((void)(x))
-
-// ************** Deprecated ***************
-
-#if (CRYPTOPP_GCC_VERSION >= 40500) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20800) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40200)
-# define CRYPTOPP_DEPRECATED(msg) __attribute__((deprecated (msg)))
-#elif (CRYPTOPP_GCC_VERSION)
-# define CRYPTOPP_DEPRECATED(msg) __attribute__((deprecated))
-#else
-# define CRYPTOPP_DEPRECATED(msg)
-#endif
-
-// ************** Instrumentation ***************
-
-// GCC does not support; see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=78204
-#if (CRYPTOPP_LLVM_CLANG_VERSION >= 30700) || (CRYPTOPP_APPLE_CLANG_VERSION >= 70000)
-# define CRYPTOPP_NO_SANITIZE(x) __attribute__((no_sanitize(x)))
-#else
-# define CRYPTOPP_NO_SANITIZE(x)
-#endif
-
-// ***************** C++11 related ********************
-
-// Visual Studio began at VS2010, http://msdn.microsoft.com/en-us/library/hh567368%28v=vs.110%29.aspx
-//   and https://docs.microsoft.com/en-us/cpp/visual-cpp-language-conformance .
-// Intel, http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler
-// GCC, http://gcc.gnu.org/projects/cxx0x.html
-// Clang, http://clang.llvm.org/cxx_status.html
-
-// Compatibility with non-clang compilers.
-#ifndef __has_feature
-# define __has_feature(x) 0
-#endif
-
-#if !defined(CRYPTOPP_NO_CXX11)
-#  if ((_MSC_VER >= 1600) || (__cplusplus >= 201103L)) && !defined(_STLPORT_VERSION)
-#    define CRYPTOPP_CXX11 1
-#  endif
-#endif
-
-// Hack ahead. Apple's standard library does not have C++'s unique_ptr in C++11. We can't
-//   test for unique_ptr directly because some of the non-Apple Clangs on OS X fail the same
-//   way. However, modern standard libraries have <forward_list>, so we test for it instead.
-//   Thanks to Jonathan Wakely for devising the clever test for modern/ancient versions.
-// TODO: test under Xcode 3, where g++ is really g++.
-#if defined(__APPLE__) && defined(__clang__)
-#  if !(defined(__has_include) && __has_include(<forward_list>))
-#    undef CRYPTOPP_CXX11
-#  endif
-#endif
-
-// C++11 or C++14 is available
-#if defined(CRYPTOPP_CXX11)
-
-// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; Intel 13.0; SunCC 5.14.
-#if (CRYPTOPP_MSC_VERSION >= 1700) || __has_feature(cxx_atomic) || \
-	(__INTEL_COMPILER >= 1300) || (CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5140)
-# define CRYPTOPP_CXX11_ATOMICS 1
-#endif // atomics
-
-// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; Intel 12.0; SunCC 5.13.
-// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
-#if (CRYPTOPP_MSC_VERSION >= 1700) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || \
-	(CRYPTOPP_APPLE_CLANG_VERSION >= 50000) || (__INTEL_COMPILER >= 1200) || \
-	(CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5130)
-// Hack ahead. New GCC compilers like GCC 6 on AIX 7.0 or earlier as well as original MinGW
-// don't have the synchronization gear. However, Wakely's test used for Apple does not work
-// on the GCC/AIX combination. Another twist is we need other stuff from C++11,
-// like no-except destructors. Dumping preprocessors shows the following may
-// apply: http://stackoverflow.com/q/14191566/608639.
-# include <cstddef>
-# if !defined(__GLIBCXX__) || defined(_GLIBCXX_HAS_GTHREADS)
-#  define CRYPTOPP_CXX11_SYNCHRONIZATION 1
-# endif
-#endif // synchronization
-
-// Dynamic Initialization and Destruction with Concurrency ("Magic Statics")
-// MS at VS2015 with Vista (19.00); GCC at 4.3; LLVM Clang at 2.9; Apple Clang at 4.0; Intel 11.1; SunCC 5.13.
-// Microsoft's implementation only works for Vista and above, so its further
-// limited. http://connect.microsoft.com/VisualStudio/feedback/details/1789709
-#if (CRYPTOPP_MSC_VERSION >= 1900) && ((WINVER >= 0x0600) || (_WIN32_WINNT >= 0x0600)) || \
-	(CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000)  || \
-	(__INTEL_COMPILER >= 1110) || (CRYPTOPP_GCC_VERSION >= 40300) || (__SUNPRO_CC >= 0x5130)
-# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
-#endif // Dynamic Initialization compilers
-
-// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.0; Intel 15.0; SunCC 5.13.
-#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_alignas) || \
-	(__INTEL_COMPILER >= 1500) || (CRYPTOPP_GCC_VERSION >= 40800) || (__SUNPRO_CC >= 0x5130)
-#  define CRYPTOPP_CXX11_ALIGNAS 1
-#endif // alignas
-
-// alignof: MS at VS2015 (19.00); GCC at 4.5; Clang at 2.9; Intel 15.0; SunCC 5.13.
-#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_alignof) || \
-	(__INTEL_COMPILER >= 1500) || (CRYPTOPP_GCC_VERSION >= 40500) || (__SUNPRO_CC >= 0x5130)
-#  define CRYPTOPP_CXX11_ALIGNOF 1
-#endif // alignof
-
-// lambdas: MS at VS2012 (17.00); GCC at 4.9; Clang at 3.3; Intel 12.0; SunCC 5.14.
-#if (CRYPTOPP_MSC_VERSION >= 1700) || __has_feature(cxx_lambdas) || \
-	(__INTEL_COMPILER >= 1200) || (CRYPTOPP_GCC_VERSION >= 40900) || (__SUNPRO_CC >= 0x5140)
-#  define CRYPTOPP_CXX11_LAMBDA 1
-#endif // lambdas
-
-// noexcept: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 14.0; SunCC 5.13.
-#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_noexcept) || \
-	(__INTEL_COMPILER >= 1400) || (CRYPTOPP_GCC_VERSION >= 40600) || (__SUNPRO_CC >= 0x5130)
-# define CRYPTOPP_CXX11_NOEXCEPT 1
-#endif // noexcept compilers
-
-// variadic templates: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; Intel 12.1; SunCC 5.13.
-#if (CRYPTOPP_MSC_VERSION >= 1800) || __has_feature(cxx_variadic_templates) || \
-	(__INTEL_COMPILER >= 1210) || (CRYPTOPP_GCC_VERSION >= 40300) || (__SUNPRO_CC >= 0x5130)
-# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
-#endif // variadic templates
-
-// constexpr: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.1; Intel 16.0; SunCC 5.13.
-// Intel has mis-supported the feature since at least ICPC 13.00
-#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_constexpr) || \
-	(__INTEL_COMPILER >= 1600) || (CRYPTOPP_GCC_VERSION >= 40600) || (__SUNPRO_CC >= 0x5130)
-# define CRYPTOPP_CXX11_CONSTEXPR 1
-#endif // constexpr compilers
-
-// strong typed enums: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Intel 14.0; SunCC 5.12.
-//   Mircorosft and Intel had partial support earlier, but we require full support.
-#if (CRYPTOPP_MSC_VERSION >= 1700) || __has_feature(cxx_strong_enums) || \
-	(__INTEL_COMPILER >= 1400) || (CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5120)
-# define CRYPTOPP_CXX11_ENUM 1
-#endif // constexpr compilers
-
-// nullptr_t: MS at VS2010 (16.00); GCC at 4.6; Clang at 3.3; Intel 10.0; SunCC 5.13.
-#if (CRYPTOPP_MSC_VERSION >= 1600) || __has_feature(cxx_nullptr) || \
-	(__INTEL_COMPILER >= 1000) || (CRYPTOPP_GCC_VERSION >= 40600) || (__SUNPRO_CC >= 0x5130)
-# define CRYPTOPP_CXX11_NULLPTR 1
-#endif // nullptr_t compilers
-
-#endif // CRYPTOPP_CXX11
-
-// ***************** C++17 related ********************
-
-// C++17 macro version, https://stackoverflow.com/q/38456127/608639
-#if defined(CRYPTOPP_CXX11) && !defined(CRYPTOPP_NO_CXX17)
-#  if ((_MSC_VER >= 1900) || (__cplusplus >= 201703L)) && !defined(_STLPORT_VERSION)
-#    define CRYPTOPP_CXX17 1
-#  endif
-#endif
-
-// C++17 is available
-#if defined(CRYPTOPP_CXX17)
-
-// C++17 uncaught_exceptions: MS at VS2015 (19.00); GCC at 6.0; Clang at 3.5; Intel 18.0.
-// Clang and __EXCEPTIONS see http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html
-#if defined(__clang__)
-# if __EXCEPTIONS && __has_feature(cxx_exceptions)
-#  define CRYPTOPP_CXX17_EXCEPTIONS 1
-# endif
-#elif (CRYPTOPP_MSC_VERSION >= 1900) || (__INTEL_COMPILER >= 1800) || (CRYPTOPP_GCC_VERSION >= 60000)
-# define CRYPTOPP_CXX17_EXCEPTIONS 1
-#endif // uncaught_exceptions compilers
-
-#endif  // CRYPTOPP_CXX17
-
-// ***************** C++ fixups ********************
-
-#if defined(CRYPTOPP_CXX11_NOEXCEPT)
-#  define CRYPTOPP_THROW noexcept(false)
-#  define CRYPTOPP_NO_THROW noexcept(true)
-#else
-#  define CRYPTOPP_THROW
-#  define CRYPTOPP_NO_THROW
-#endif // CRYPTOPP_CXX11_NOEXCEPT
-
-// http://stackoverflow.com/a/13867690/608639
-#if defined(CRYPTOPP_CXX11_CONSTEXPR)
-#  define CRYPTOPP_STATIC_CONSTEXPR static constexpr
-#  define CRYPTOPP_CONSTEXPR constexpr
-#else
-#  define CRYPTOPP_STATIC_CONSTEXPR static
-#  define CRYPTOPP_CONSTEXPR
-#endif // CRYPTOPP_CXX11_CONSTEXPR
-
-// Hack... CRYPTOPP_ALIGN_DATA is defined earlier, before C++11 alignas availability is determined
-#if defined(CRYPTOPP_CXX11_ALIGNAS)
-# undef CRYPTOPP_ALIGN_DATA
-# define CRYPTOPP_ALIGN_DATA(x) alignas(x)
-#endif  // CRYPTOPP_CXX11_ALIGNAS
-
-// Hack... CRYPTOPP_CONSTANT is defined earlier, before C++11 constexpr availability is determined
-// http://stackoverflow.com/q/35213098/608639
-// #if defined(CRYPTOPP_CXX11_CONSTEXPR)
-// # undef CRYPTOPP_CONSTANT
-// # define CRYPTOPP_CONSTANT(x) constexpr static int x;
-// #endif
-
-// Hack... CRYPTOPP_CONSTANT is defined earlier, before C++11 constexpr availability is determined
-// http://stackoverflow.com/q/35213098/608639
-#if defined(CRYPTOPP_CXX11_ENUM)
-# undef CRYPTOPP_CONSTANT
-# define CRYPTOPP_CONSTANT(x) enum : int { x };
-#elif defined(CRYPTOPP_CXX11_CONSTEXPR)
-# undef CRYPTOPP_CONSTANT
-# define CRYPTOPP_CONSTANT(x) constexpr static int x;
-#endif
-
-// Hack... C++11 nullptr_t type safety and analysis
-#if defined(CRYPTOPP_CXX11_NULLPTR) && !defined(NULLPTR)
-# define NULLPTR nullptr
-#elif !defined(NULLPTR)
-# define NULLPTR NULL
-#endif // CRYPTOPP_CXX11_NULLPTR
-
-// OK to comment the following out, but please report it so we can fix it.
-// C++17 value taken from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf.
-#if (defined(__cplusplus) && (__cplusplus >= 199711L) && (__cplusplus < 201402L)) && !defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
-# error "std::uncaught_exception is not available. This is likely a configuration error."
-#endif
-
-#endif  // CRYPTOPP_CONFIG_H
+#include "config_align.h"
+#include "config_asm.h"
+#include "config_cpu.h"
+#include "config_cxx.h"
+#include "config_dll.h"
+#include "config_int.h"
+#include "config_misc.h"
+#include "config_ns.h"
+#include "config_os.h"
+#include "config_ver.h"
+
+#endif // CRYPTOPP_CONFIG_H

+ 72 - 0
include/cryptlib/config_align.h

@@ -0,0 +1,72 @@
+// config_align.h - written and placed in public domain by Jeffrey Walton
+//                  the bits that make up this source file are from the
+//                  library's monolithic config.h.
+
+/// \file config_align.h
+/// \brief Library configuration file
+/// \details <tt>config_align.h</tt> provides defines for aligned memory
+///  allocations.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_align.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_ALIGN_H
+#define CRYPTOPP_CONFIG_ALIGN_H
+
+#include "config_asm.h"  // CRYPTOPP_DISABLE_ASM
+#include "config_cpu.h"  // X86, X32, X64, ARM32, ARM64, etc
+#include "config_cxx.h"  // CRYPTOPP_CXX11_ALIGNAS
+#include "config_ver.h"  // Compiler versions
+
+// Nearly all Intel's and AMD's have SSE. Enable it independent of SSE ASM and intrinsics.
+// ARM NEON and ARMv8 ASIMD only need natural alignment of an element in the vector.
+// Altivec through POWER7 need vector alignment. POWER8 and POWER9 relax the requirement.
+#if defined(CRYPTOPP_DISABLE_ASM)
+	#define CRYPTOPP_BOOL_ALIGN16 0
+#elif (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 || \
+       CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
+	#define CRYPTOPP_BOOL_ALIGN16 1
+#else
+	#define CRYPTOPP_BOOL_ALIGN16 0
+#endif
+
+// How to allocate 16-byte aligned memory (for SSE2)
+// posix_memalign see https://forum.kde.org/viewtopic.php?p=66274
+#if defined(CRYPTOPP_MSC_VERSION)
+	#define CRYPTOPP_MM_MALLOC_AVAILABLE
+#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+	#define CRYPTOPP_MEMALIGN_AVAILABLE
+#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+	#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
+#elif (defined(_GNU_SOURCE) || ((_XOPEN_SOURCE + 0) >= 600)) && (_POSIX_ADVISORY_INFO > 0)
+	#define CRYPTOPP_POSIX_MEMALIGN_AVAILABLE
+#else
+	#define CRYPTOPP_NO_ALIGNED_ALLOC
+#endif
+
+// Sun Studio Express 3 (December 2006) provides GCC-style attributes.
+// IBM XL C/C++ alignment modifier per Optimization Guide, pp. 19-20.
+// __IBM_ATTRIBUTES per XLC 12.1 AIX Compiler Manual, p. 473.
+// CRYPTOPP_ALIGN_DATA may not be reliable on AIX.
+#if defined(CRYPTOPP_CXX11_ALIGNAS)
+	#define CRYPTOPP_ALIGN_DATA(x) alignas(x)
+#elif defined(CRYPTOPP_MSC_VERSION)
+	#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
+#elif defined(__GNUC__) || defined(__clang__) || (__SUNPRO_CC >= 0x5100)
+	#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
+#elif defined(__xlc__) || defined(__xlC__)
+	#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
+#else
+	#define CRYPTOPP_ALIGN_DATA(x)
+#endif
+
+#endif  // CRYPTOPP_CONFIG_ALIGN_H

+ 492 - 0
include/cryptlib/config_asm.h

@@ -0,0 +1,492 @@
+// config_asm.h - written and placed in public domain by Jeffrey Walton
+//                the bits that make up this source file are from the
+//                library's monolithic config.h.
+
+/// \file config_asm.h
+/// \brief Library configuration file
+/// \details <tt>config_asm.h</tt> provides defines for instruction set
+///  architectures
+///  and inline assembly.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_asm.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_ASM_H
+#define CRYPTOPP_CONFIG_ASM_H
+
+#include "config_os.h"
+#include "config_cpu.h"
+#include "config_ver.h"
+
+// Define this to disable ASM, intrinsics and built-ins. The library will be
+// compiled using C++ only. The library code will not include SSE2 (and
+// above), NEON, Aarch32, Aarch64, or Altivec (and above). Note the compiler
+// may use higher ISAs depending on compiler options, but the library will not
+// explicitly use the ISAs. When disabling ASM, it is best to do it from
+// config.h to ensure the library and all programs share the setting.
+// #define CRYPTOPP_DISABLE_ASM 1
+
+// https://github.com/weidai11/cryptopp/issues/719
+#if defined(__native_client__)
+# undef CRYPTOPP_DISABLE_ASM
+# define CRYPTOPP_DISABLE_ASM 1
+#endif
+
+// Some Clang and SunCC cannot handle mixed asm with positional arguments,
+// where the body is Intel style with no prefix and the templates are
+// AT&T style. Define this if the Makefile misdetects the configuration.
+// Also see https://bugs.llvm.org/show_bug.cgi?id=39895 .
+// #define CRYPTOPP_DISABLE_MIXED_ASM 1
+
+#if defined(__clang__) || (defined(__APPLE__) && defined(__GNUC__)) || defined(__SUNPRO_CC)
+# undef CRYPTOPP_DISABLE_MIXED_ASM
+# define CRYPTOPP_DISABLE_MIXED_ASM 1
+#endif
+
+// Define this if you need to disable Android advanced ISAs.
+// The problem is, Android-mk does not allow us to specify an
+// ISA option, like -maes or -march=armv8-a+crypto for AES.
+// Lack of an option results in a compile failure. To avoid
+// the compile failure, set this define. Also see
+// https://github.com/weidai11/cryptopp/issues/1015
+// CRYPTOPP_DISABLE_ANDROID_ADVANCED_ISA 1
+
+// ***************** IA32 CPU features ********************
+
+#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
+
+// Apple Clang prior to 5.0 cannot handle SSE2
+#if defined(CRYPTOPP_APPLE_CLANG_VERSION) && (CRYPTOPP_APPLE_CLANG_VERSION < 50000)
+# define CRYPTOPP_DISABLE_ASM 1
+#endif
+
+// Sun Studio 12.1 provides GCC inline assembly
+// http://blogs.oracle.com/x86be/entry/gcc_style_asm_inlining_support
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5100)
+# define CRYPTOPP_DISABLE_ASM 1
+#endif
+
+// Guard everything in CRYPTOPP_DISABLE_ASM
+#if !defined(CRYPTOPP_DISABLE_ASM)
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || ((defined(__GNUC__) && (defined(__i386__)) || defined(__x86_64__)))
+	// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
+	#define CRYPTOPP_X86_ASM_AVAILABLE 1
+
+	#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(_MSC_VER) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__))
+		#define CRYPTOPP_SSE2_ASM_AVAILABLE 1
+	#endif
+
+	#if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1500 || CRYPTOPP_GCC_VERSION >= 40300 || defined(__SSSE3__))
+		#define CRYPTOPP_SSSE3_ASM_AVAILABLE 1
+	#endif
+#endif
+
+#if defined(_MSC_VER) && defined(_M_X64)
+	#define CRYPTOPP_X64_MASM_AVAILABLE 1
+#endif
+
+#if defined(__GNUC__) && defined(__x86_64__)
+	#define CRYPTOPP_X64_ASM_AVAILABLE 1
+#endif
+
+// 32-bit SunCC does not enable SSE2 by default.
+#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSC_VERSION) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__) || (__SUNPRO_CC >= 0x5100))
+	#define CRYPTOPP_SSE2_INTRIN_AVAILABLE 1
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_SSSE3)
+# if defined(__SSSE3__) || (CRYPTOPP_MSC_VERSION >= 1500) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || (__SUNPRO_CC >= 0x5110) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000)
+	#define CRYPTOPP_SSSE3_AVAILABLE 1
+# endif
+#endif
+
+// Intrinsics available in GCC 4.3 (http://gcc.gnu.org/gcc-4.3/changes.html) and
+// MSVC 2008 (http://msdn.microsoft.com/en-us/library/bb892950%28v=vs.90%29.aspx)
+// SunCC could generate SSE4 at 12.1, but the intrinsics are missing until 12.4.
+#if !defined(CRYPTOPP_DISABLE_SSE4) && defined(CRYPTOPP_SSSE3_AVAILABLE) && \
+	(defined(__SSE4_1__) || (CRYPTOPP_MSC_VERSION >= 1500) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || (__SUNPRO_CC >= 0x5110) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000))
+	#define CRYPTOPP_SSE41_AVAILABLE 1
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_SSE4) && defined(CRYPTOPP_SSSE3_AVAILABLE) && \
+	(defined(__SSE4_2__) || (CRYPTOPP_MSC_VERSION >= 1500) || (__SUNPRO_CC >= 0x5110) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1000) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 20300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000))
+	#define CRYPTOPP_SSE42_AVAILABLE 1
+#endif
+
+// Couple to CRYPTOPP_DISABLE_AESNI, but use CRYPTOPP_CLMUL_AVAILABLE so we can selectively
+//  disable for misbehaving platforms and compilers, like Solaris or some Clang.
+#if defined(CRYPTOPP_DISABLE_AESNI)
+	#define CRYPTOPP_DISABLE_CLMUL 1
+#endif
+
+// Requires Sun Studio 12.3 (SunCC 0x5120) in theory.
+#if !defined(CRYPTOPP_DISABLE_CLMUL) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
+	(defined(__PCLMUL__) || (_MSC_FULL_VER >= 150030729) || (__SUNPRO_CC >= 0x5120) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1110) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 30200) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300))
+	#define CRYPTOPP_CLMUL_AVAILABLE 1
+#endif
+
+// Requires Sun Studio 12.3 (SunCC 0x5120)
+#if !defined(CRYPTOPP_DISABLE_AESNI) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
+	(defined(__AES__) || (_MSC_FULL_VER >= 150030729) || (__SUNPRO_CC >= 0x5120) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__INTEL_COMPILER >= 1110) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 30200) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300))
+	#define CRYPTOPP_AESNI_AVAILABLE 1
+#endif
+
+// Requires Binutils 2.24
+#if !defined(CRYPTOPP_DISABLE_AVX) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
+	(defined(__AVX2__) || (CRYPTOPP_MSC_VERSION >= 1800) || (__SUNPRO_CC >= 0x5130) || \
+	(CRYPTOPP_GCC_VERSION >= 40700) || (__INTEL_COMPILER >= 1400) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 30100) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40600))
+#define CRYPTOPP_AVX_AVAILABLE 1
+#endif
+
+// Requires Binutils 2.24
+#if !defined(CRYPTOPP_DISABLE_AVX2) && defined(CRYPTOPP_AVX_AVAILABLE) && \
+	(defined(__AVX2__) || (CRYPTOPP_MSC_VERSION >= 1800) || (__SUNPRO_CC >= 0x5130) || \
+	(CRYPTOPP_GCC_VERSION >= 40900) || (__INTEL_COMPILER >= 1400) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 30100) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40600))
+#define CRYPTOPP_AVX2_AVAILABLE 1
+#endif
+
+// Guessing at SHA for SunCC. Its not in Sun Studio 12.6. Also see
+// http://stackoverflow.com/questions/45872180/which-xarch-for-sha-extensions-on-solaris
+// Guessing for Intel ICPC. A slide deck says SHA support is in version 16.0-beta
+// https://www.alcf.anl.gov/files/ken_intel_compiler_optimization.pdf
+#if !defined(CRYPTOPP_DISABLE_SHANI) && defined(CRYPTOPP_SSE42_AVAILABLE) && \
+	(defined(__SHA__) || (CRYPTOPP_MSC_VERSION >= 1900) || (__SUNPRO_CC >= 0x5160) || \
+	(CRYPTOPP_GCC_VERSION >= 40900) || (__INTEL_COMPILER >= 1600) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 30400) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50100))
+	#define CRYPTOPP_SHANI_AVAILABLE 1
+#endif
+
+// RDRAND uses byte codes. All we need is x86 ASM for it.
+// However tie it to AES-NI since SecureKey was available with it.
+#if !defined(CRYPTOPP_DISABLE_RDRAND) && defined(CRYPTOPP_AESNI_AVAILABLE)
+	#define CRYPTOPP_RDRAND_AVAILABLE 1
+#endif
+
+// RDSEED uses byte codes. All we need is x86 ASM for it.
+// However tie it to AES-NI since SecureKey was available with it.
+#if !defined(CRYPTOPP_DISABLE_RDSEED) && defined(CRYPTOPP_AESNI_AVAILABLE)
+	#define CRYPTOPP_RDSEED_AVAILABLE 1
+#endif
+
+// PadlockRNG uses byte codes. All we need is x86 ASM for it.
+#if !defined(CRYPTOPP_DISABLE_PADLOCK) && \
+	!(defined(__ANDROID__) || defined(ANDROID) || defined(__APPLE__)) && \
+	defined(CRYPTOPP_X86_ASM_AVAILABLE)
+	#define CRYPTOPP_PADLOCK_AVAILABLE 1
+	#define CRYPTOPP_PADLOCK_RNG_AVAILABLE 1
+	#define CRYPTOPP_PADLOCK_ACE_AVAILABLE 1
+	#define CRYPTOPP_PADLOCK_ACE2_AVAILABLE 1
+	#define CRYPTOPP_PADLOCK_PHE_AVAILABLE 1
+	#define CRYPTOPP_PADLOCK_PMM_AVAILABLE 1
+#endif
+
+// Fixup for SunCC 12.1-12.4. Bad code generation in AES_Encrypt and friends.
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x5130)
+# undef CRYPTOPP_AESNI_AVAILABLE
+#endif
+
+// Fixup for SunCC 12.1-12.6. Compiler crash on GCM_Reduce_CLMUL.
+// http://github.com/weidai11/cryptopp/issues/226
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x5150)
+# undef CRYPTOPP_CLMUL_AVAILABLE
+#endif
+
+// Clang intrinsic casts, http://bugs.llvm.org/show_bug.cgi?id=20670
+#define M128_CAST(x) ((__m128i *)(void *)(x))
+#define CONST_M128_CAST(x) ((const __m128i *)(const void *)(x))
+#define M256_CAST(x) ((__m256i *)(void *)(x))
+#define CONST_M256_CAST(x) ((const __m256i *)(const void *)(x))
+
+#endif  // CRYPTOPP_DISABLE_ASM
+
+#endif  // X86, X32, X64
+
+// ***************** ARM CPU features ********************
+
+#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
+
+// We don't have an ARM big endian test rig. Disable
+// ARM-BE ASM and instrinsics until we can test it.
+#if (CRYPTOPP_BIG_ENDIAN)
+# define CRYPTOPP_DISABLE_ASM 1
+#endif
+
+// Guard everything in CRYPTOPP_DISABLE_ASM
+#if !defined(CRYPTOPP_DISABLE_ASM)
+
+// Requires ACLE 1.0. -mfpu=neon or above must be present
+// Requires GCC 4.3, Clang 2.8 or Visual Studio 2012
+// Do not use APPLE_CLANG_VERSION; use __ARM_FEATURE_XXX instead.
+#if !defined(CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_NEON)
+# if defined(__arm__) || defined(__ARM_NEON) || defined(__ARM_FEATURE_NEON) || defined(_M_ARM)
+#  if (CRYPTOPP_GCC_VERSION >= 40300) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20800) || \
+      (CRYPTOPP_APPLE_CLANG_VERSION >= 30200) || (CRYPTOPP_MSC_VERSION >= 1700)
+#   define CRYPTOPP_ARM_NEON_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// ARMv8 and ASIMD. -march=armv8-a or above must be present
+// Requires GCC 4.8, Clang 3.3 or Visual Studio 2017
+// Do not use APPLE_CLANG_VERSION; use __ARM_FEATURE_XXX instead.
+#if !defined(CRYPTOPP_ARM_ASIMD_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_ASIMD)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
+#  if defined(__ARM_NEON) || defined(__ARM_ASIMD) || defined(__ARM_FEATURE_NEON) || defined(__ARM_FEATURE_ASIMD) || \
+      (CRYPTOPP_GCC_VERSION >= 40800) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || \
+      (CRYPTOPP_APPLE_CLANG_VERSION >= 40000) || (CRYPTOPP_MSC_VERSION >= 1916)
+#   define CRYPTOPP_ARM_NEON_AVAILABLE 1
+#   define CRYPTOPP_ARM_ASIMD_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// ARMv8 and ASIMD. -march=armv8-a+crc or above must be present
+// Requires GCC 4.8, Clang 3.3 or Visual Studio 2017
+#if !defined(CRYPTOPP_ARM_CRC32_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_CRC32)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+#  if defined(__ARM_FEATURE_CRC32) || (CRYPTOPP_GCC_VERSION >= 40800) || \
+      (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300) || \
+      (CRYPTOPP_MSC_VERSION >= 1916)
+#   define CRYPTOPP_ARM_CRC32_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// ARMv8 and AES. -march=armv8-a+crypto or above must be present
+// Requires GCC 4.8, Clang 3.3 or Visual Studio 2017
+#if !defined(CRYPTOPP_ARM_AES_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_AES)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+#  if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \
+      (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300) || \
+      (CRYPTOPP_MSC_VERSION >= 1916)
+#   define CRYPTOPP_ARM_AES_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// ARMv8 and PMULL. -march=armv8-a+crypto or above must be present
+// Requires GCC 4.8, Clang 3.3 or Visual Studio 2017
+#if !defined(CRYPTOPP_ARM_PMULL_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_PMULL)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+#  if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \
+      (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300) || \
+      (CRYPTOPP_MSC_VERSION >= 1916)
+#   define CRYPTOPP_ARM_PMULL_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// ARMv8 and SHA-1, SHA-256. -march=armv8-a+crypto or above must be present
+// Requires GCC 4.8, Clang 3.3 or Visual Studio 2017
+#if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_SHA)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+#  if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \
+      (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300) || \
+      (CRYPTOPP_MSC_VERSION >= 1916)
+#   define CRYPTOPP_ARM_SHA1_AVAILABLE 1
+#   define CRYPTOPP_ARM_SHA2_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// Buggy Microsoft compiler, https://github.com/weidai11/cryptopp/issues/1096
+#if defined(CRYPTOPP_MSC_VERSION)
+# undef CRYPTOPP_ARM_SHA1_AVAILABLE
+# undef CRYPTOPP_ARM_SHA2_AVAILABLE
+#endif
+
+// ARMv8 and SHA-512, SHA-3. -march=armv8.2-a+crypto or above must be present
+// Requires GCC 8.0, Clang 11.0, Apple Clang 12.0 or Visual Studio 20??
+#if !defined(CRYPTOPP_ARM_SHA3_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_SHA)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+#  if defined(__ARM_FEATURE_SHA3) || (CRYPTOPP_GCC_VERSION >= 80000) || \
+      (CRYPTOPP_APPLE_CLANG_VERSION >= 120000) || (CRYPTOPP_LLVM_CLANG_VERSION >= 110000)
+#   define CRYPTOPP_ARM_SHA512_AVAILABLE 1
+#   define CRYPTOPP_ARM_SHA3_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// ARMv8 and SM3, SM4. -march=armv8.2-a+crypto or above must be present
+// Requires GCC 8.0, Clang ??? or Visual Studio 20??
+// Do not use APPLE_CLANG_VERSION; use __ARM_FEATURE_XXX instead.
+#if !defined(CRYPTOPP_ARM_SM3_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ARM_SM3)
+# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+#  if defined(__ARM_FEATURE_SM3) || (CRYPTOPP_GCC_VERSION >= 80000)
+#   define CRYPTOPP_ARM_SM3_AVAILABLE 1
+#   define CRYPTOPP_ARM_SM4_AVAILABLE 1
+#  endif  // Compilers
+# endif  // Platforms
+#endif
+
+// Limit the <arm_neon.h> include.
+#if !defined(CRYPTOPP_ARM_NEON_HEADER)
+# if defined(CRYPTOPP_ARM_NEON_AVAILABLE) || defined (CRYPTOPP_ARM_ASIMD_AVAILABLE)
+#  if !defined(_M_ARM64)
+#   define CRYPTOPP_ARM_NEON_HEADER 1
+#  endif
+# endif
+#endif
+
+// Limit the <arm_acle.h> include.
+#if !defined(CRYPTOPP_ARM_ACLE_HEADER)
+# if defined(__aarch32__) || defined(__aarch64__) || (__ARM_ARCH >= 8) || defined(__ARM_ACLE)
+#  define CRYPTOPP_ARM_ACLE_HEADER 1
+# endif
+#endif
+
+// Apple M1 hack. Xcode cross-compiles for iOS lack
+// arm_acle.h. Apple M1 needs arm_acle.h. The problem
+// in practice is, we can't get CRYPTOPP_ARM_ACLE_HEADER
+// quite right based on ARM preprocessor macros.
+#if defined(__APPLE__) && !defined(__ARM_FEATURE_CRC32)
+# undef CRYPTOPP_ARM_ACLE_HEADER
+#endif
+
+// Cryptogams offers an ARM asm implementations for AES and SHA. Crypto++ does
+// not provide an asm implementation. The Cryptogams AES implementation is
+// about 50% faster than C/C++, and SHA implementation is about 30% faster
+// than C/C++. Define this to use the Cryptogams AES and SHA implementations
+// on GNU Linux systems. When defined, Crypto++ will use aes_armv4.S,
+// sha1_armv4.S and sha256_armv4.S. https://www.cryptopp.com/wiki/Cryptogams.
+#if !defined(CRYPTOPP_DISABLE_ARM_NEON)
+# if defined(__arm__) && defined(__linux__)
+#  if defined(__GNUC__) || defined(__clang__)
+#   define CRYPTOGAMS_ARM_AES      1
+#   define CRYPTOGAMS_ARM_SHA1     1
+#   define CRYPTOGAMS_ARM_SHA256   1
+#   define CRYPTOGAMS_ARM_SHA512   1
+#  endif
+# endif
+#endif
+
+// We are still having trouble with integrating Cryptogams AES. Ugh...
+// https://github.com/weidai11/cryptopp/issues/1236
+#undef CRYPTOGAMS_ARM_AES
+
+// Clang intrinsic casts, http://bugs.llvm.org/show_bug.cgi?id=20670
+#define UINT64_CAST(x) ((uint64_t *)(void *)(x))
+#define CONST_UINT64_CAST(x) ((const uint64_t *)(const void *)(x))
+
+#endif  // CRYPTOPP_DISABLE_ASM
+
+#endif  // ARM32, ARM64
+
+// ***************** AltiVec and Power8 ********************
+
+#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
+
+// Guard everything in CRYPTOPP_DISABLE_ASM
+#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_ALTIVEC)
+
+// An old Apple G5 with GCC 4.01 has AltiVec, but its only Power4 or so.
+#if !defined(CRYPTOPP_ALTIVEC_AVAILABLE)
+# if defined(_ARCH_PWR4) || defined(__ALTIVEC__) || \
+	(CRYPTOPP_XLC_VERSION >= 100000) || (CRYPTOPP_GCC_VERSION >= 40001) || \
+    (CRYPTOPP_LLVM_CLANG_VERSION >= 20900)
+#  define CRYPTOPP_ALTIVEC_AVAILABLE 1
+# endif
+#endif
+
+#if defined(CRYPTOPP_ALTIVEC_AVAILABLE)
+
+// We need Power7 for unaligned loads and stores
+#if !defined(CRYPTOPP_POWER7_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER7)
+# if defined(_ARCH_PWR7) || (CRYPTOPP_XLC_VERSION >= 100000) || \
+    (CRYPTOPP_GCC_VERSION >= 40100) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30100)
+#  define CRYPTOPP_POWER7_AVAILABLE 1
+# endif
+#endif
+
+#if defined(CRYPTOPP_POWER7_AVAILABLE)
+
+// We need Power8 for in-core crypto and 64-bit vector types
+#if !defined(CRYPTOPP_POWER8_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER8)
+# if defined(_ARCH_PWR8) || (CRYPTOPP_XLC_VERSION >= 130000) || \
+    (CRYPTOPP_GCC_VERSION >= 40800) || (CRYPTOPP_LLVM_CLANG_VERSION >= 70000)
+#  define CRYPTOPP_POWER8_AVAILABLE 1
+# endif
+#endif
+
+#if !defined(CRYPTOPP_POWER8_AES_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER8_AES) && defined(CRYPTOPP_POWER8_AVAILABLE)
+# if defined(__CRYPTO__) || defined(_ARCH_PWR8) || (CRYPTOPP_XLC_VERSION >= 130000) || \
+    (CRYPTOPP_GCC_VERSION >= 40800) || (CRYPTOPP_LLVM_CLANG_VERSION >= 70000)
+//#  define CRYPTOPP_POWER8_CRC_AVAILABLE 1
+#  define CRYPTOPP_POWER8_AES_AVAILABLE 1
+#  define CRYPTOPP_POWER8_VMULL_AVAILABLE 1
+#  define CRYPTOPP_POWER8_SHA_AVAILABLE 1
+# endif
+#endif
+
+#if defined(CRYPTOPP_POWER8_AVAILABLE)
+
+// Power9 for random numbers
+#if !defined(CRYPTOPP_POWER9_AVAILABLE) && !defined(CRYPTOPP_DISABLE_POWER9)
+# if defined(_ARCH_PWR9) || (CRYPTOPP_XLC_VERSION >= 130200) || \
+    (CRYPTOPP_GCC_VERSION >= 70000) || (CRYPTOPP_LLVM_CLANG_VERSION >= 80000)
+#  define CRYPTOPP_POWER9_AVAILABLE 1
+# endif
+#endif
+
+#endif  // CRYPTOPP_POWER8_AVAILABLE
+#endif  // CRYPTOPP_POWER7_AVAILABLE
+#endif  // CRYPTOPP_ALTIVEC_AVAILABLE
+#endif  // CRYPTOPP_DISABLE_ASM
+#endif  // PPC32, PPC64
+
+// https://github.com/weidai11/cryptopp/issues/1015
+#if defined(CRYPTOPP_DISABLE_ANDROID_ADVANCED_ISA)
+# if defined(__ANDROID__) || defined(ANDROID)
+#  if (CRYPTOPP_BOOL_X86)
+#   undef CRYPTOPP_SSE41_AVAILABLE
+#   undef CRYPTOPP_SSE42_AVAILABLE
+#   undef CRYPTOPP_CLMUL_AVAILABLE
+#   undef CRYPTOPP_AESNI_AVAILABLE
+#   undef CRYPTOPP_SHANI_AVAILABLE
+#   undef CRYPTOPP_RDRAND_AVAILABLE
+#   undef CRYPTOPP_RDSEED_AVAILABLE
+#   undef CRYPTOPP_AVX_AVAILABLE
+#   undef CRYPTOPP_AVX2_AVAILABLE
+#  endif
+#  if (CRYPTOPP_BOOL_X64)
+#   undef CRYPTOPP_CLMUL_AVAILABLE
+#   undef CRYPTOPP_AESNI_AVAILABLE
+#   undef CRYPTOPP_SHANI_AVAILABLE
+#   undef CRYPTOPP_RDRAND_AVAILABLE
+#   undef CRYPTOPP_RDSEED_AVAILABLE
+#   undef CRYPTOPP_AVX_AVAILABLE
+#   undef CRYPTOPP_AVX2_AVAILABLE
+#  endif
+#  if (CRYPTOPP_BOOL_ARMV8)
+#   undef CRYPTOPP_ARM_CRC32_AVAILABLE
+#   undef CRYPTOPP_ARM_PMULL_AVAILABLE
+#   undef CRYPTOPP_ARM_AES_AVAILABLE
+#   undef CRYPTOPP_ARM_SHA1_AVAILABLE
+#   undef CRYPTOPP_ARM_SHA2_AVAILABLE
+#  endif
+# endif  // ANDROID
+#endif   // CRYPTOPP_DISABLE_ANDROID_ADVANCED_ISA
+
+#endif  // CRYPTOPP_CONFIG_ASM_H

+ 212 - 0
include/cryptlib/config_cpu.h

@@ -0,0 +1,212 @@
+// config_cpu.h - written and placed in public domain by Jeffrey Walton
+//                the bits that make up this source file are from the
+//                library's monolithic config.h.
+
+/// \file config_cpu.h
+/// \brief Library configuration file
+/// \details <tt>config_cpu.h</tt> provides defines for the cpu and machine
+///  architecture.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_cpu.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki,
+///  <A HREF="https://sourceforge.net/p/predef/wiki/Architectures/">Sourceforge
+///  Pre-defined Compiler Macros</A>
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_CPU_H
+#define CRYPTOPP_CONFIG_CPU_H
+
+#include "config_ver.h"
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief 32-bit x32 platform
+	/// \details CRYPTOPP_BOOL_X32 is defined to 1 when building the library
+	///  for a 32-bit x32 platform. Otherwise, the macro is not defined.
+	/// \details x32 is sometimes referred to as x86_32. x32 is the ILP32 data
+	///  model on a 64-bit cpu. Integers, longs and pointers are 32-bit but the
+	///  program runs on a 64-bit cpu.
+	/// \details The significance of x32 is, inline assembly must operate on
+	///  64-bit registers, not 32-bit registers. That means, for example,
+	///  function prologues and epilogues must push and pop RSP, not ESP.
+	/// \note: Clang defines __ILP32__ on any 32-bit platform. Therefore,
+	///  CRYPTOPP_BOOL_X32 depends upon both __ILP32__ and __x86_64__.
+	/// \sa <A HREF="https://wiki.debian.org/X32Port">Debian X32 Port</A>,
+	///  <A HREF="https://wiki.gentoo.org/wiki/Project:Multilib/Concepts">Gentoo
+	///  Multilib Concepts</A>
+	#define CRYPTOPP_BOOL_X32 ...
+	/// \brief 32-bit x86 platform
+	/// \details CRYPTOPP_BOOL_X64 is defined to 1 when building the library
+	///  for a 64-bit x64 platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_X64 ...
+	/// \brief 32-bit x86 platform
+	/// \details CRYPTOPP_BOOL_X86 is defined to 1 when building the library
+	///  for a 32-bit x86 platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_X86 ...
+#elif (defined(__ILP32__) || defined(_ILP32)) && defined(__x86_64__)
+	#define CRYPTOPP_BOOL_X32 1
+#elif (defined(_M_X64) || defined(__x86_64__))
+	#define CRYPTOPP_BOOL_X64 1
+#elif (defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__))
+	#define CRYPTOPP_BOOL_X86 1
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief ARMv8 platform
+	/// \details CRYPTOPP_BOOL_ARMV8 is defined to 1 when building the library
+	///  for an ARMv8 platform. Otherwise, the macro is not defined.
+	/// \details ARMv8 includes both Aarch32 and Aarch64. Aarch32 is a 32-bit
+	///  execution environment on Aarch64.
+	#define CRYPTOPP_BOOL_ARMV8 ...
+	/// \brief 64-bit ARM platform
+	/// \details CRYPTOPP_BOOL_ARM64 is defined to 1 when building the library
+	///  for a 64-bit x64 platform. Otherwise, the macro is not defined.
+	/// \details Currently the macro indicates an ARM 64-bit architecture.
+	#define CRYPTOPP_BOOL_ARM64 ...
+	/// \brief 32-bit ARM platform
+	/// \details CRYPTOPP_BOOL_ARM32 is defined to 1 when building the library
+	///  for a 32-bit ARM platform. Otherwise, the macro is not defined.
+	/// \details Currently the macro indicates an ARM A-32 architecture.
+	#define CRYPTOPP_BOOL_ARM32 ...
+#elif defined(__arm64__) || defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
+	// Microsoft added ARM64 define December 2017.
+	#define CRYPTOPP_BOOL_ARMV8 1
+#endif
+#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
+	#define CRYPTOPP_BOOL_ARM64 1
+#elif defined(__arm__) || defined(_M_ARM)
+	#define CRYPTOPP_BOOL_ARM32 1
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief 64-bit PowerPC platform
+	/// \details CRYPTOPP_BOOL_PPC64 is defined to 1 when building the library
+	///  for a 64-bit PowerPC platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_PPC64 ...
+	/// \brief 32-bit PowerPC platform
+	/// \details CRYPTOPP_BOOL_PPC32 is defined to 1 when building the library
+	///  for a 32-bit PowerPC platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_PPC32 ...
+#elif defined(__ppc64__) || defined(__powerpc64__) || defined(__PPC64__) || defined(_ARCH_PPC64)
+	#define CRYPTOPP_BOOL_PPC64 1
+#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
+	#define CRYPTOPP_BOOL_PPC32 1
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief 64-bit MIPS platform
+	/// \details CRYPTOPP_BOOL_MIPS64 is defined to 1 when building the library
+	///  for a 64-bit MIPS platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_MIPS64 ...
+	/// \brief 64-bit MIPS platform
+	/// \details CRYPTOPP_BOOL_MIPS32 is defined to 1 when building the library
+	///  for a 32-bit MIPS platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_MIPS32 ...
+#elif defined(__mips64__)
+	#define CRYPTOPP_BOOL_MIPS64 1
+#elif defined(__mips__)
+	#define CRYPTOPP_BOOL_MIPS32 1
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief 64-bit SPARC platform
+	/// \details CRYPTOPP_BOOL_SPARC64 is defined to 1 when building the library
+	///  for a 64-bit SPARC platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_SPARC64 ...
+	/// \brief 32-bit SPARC platform
+	/// \details CRYPTOPP_BOOL_SPARC32 is defined to 1 when building the library
+	///  for a 32-bit SPARC platform. Otherwise, the macro is not defined.
+	#define CRYPTOPP_BOOL_SPARC32 ...
+#elif defined(__sparc64__) || defined(__sparc64) || defined(__sparcv9) || defined(__sparc_v9__)
+	#define CRYPTOPP_BOOL_SPARC64 1
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) || defined(__sparc_v8__)
+	#define CRYPTOPP_BOOL_SPARC32 1
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief L1 data cache line size
+	/// \details CRYPTOPP_L1_CACHE_LINE_SIZE should be a lower bound on the L1
+	///  data cache line size. It is used for defense against some timing attacks.
+	/// \details CRYPTOPP_L1_CACHE_LINE_SIZE default value on 32-bit platforms
+	///  is 32, and the default value on 64-bit platforms is 64. On PowerPC the
+	///  default value is 128 since all PowerPC cpu's starting at PPC 970 provide
+	///  it.
+	/// \note The runtime library on some PowerPC platforms misreport the size
+	///  of the cache line size. The runtime library reports 64, while the cpu
+	///  has a cache line size of 128.
+	/// \sa <A HREF="https://bugs.centos.org/view.php?id=14599">CentOS Issue
+	///  14599: sysconf(_SC_LEVEL1_DCACHE_LINESIZE) returns 0 instead of 128</A>
+	/// \since Crypto++ 5.3
+	#define CRYPTOPP_L1_CACHE_LINE_SIZE ...
+#else
+	#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
+		#if defined(CRYPTOPP_BOOL_X32) || defined(CRYPTOPP_BOOL_X64) || defined(CRYPTOPP_BOOL_ARMV8) || \
+		    defined(CRYPTOPP_BOOL_MIPS64) || defined(CRYPTOPP_BOOL_SPARC64)
+			#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
+		#elif defined(CRYPTOPP_BOOL_PPC32) || defined(CRYPTOPP_BOOL_PPC64)
+			// http://lists.llvm.org/pipermail/llvm-dev/2017-March/110982.html
+			#define CRYPTOPP_L1_CACHE_LINE_SIZE 128
+		#else
+			// L1 cache line size is 32 on Pentium III and earlier
+			#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
+		#endif
+	#endif
+#endif
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief Initialized data section
+	/// \details CRYPTOPP_SECTION_INIT is added to variables to place them in the
+	///  initialized data section (sometimes denoted <tt>.data</tt>). The placement
+	///  helps avoid "uninitialized variable" warnings from Valgrind and other tools.
+	#define CRYPTOPP_SECTION_INIT ...
+#else
+	// The section attribute attempts to initialize CPU flags to avoid Valgrind findings above -O1
+	#if ((defined(__MACH__) && defined(__APPLE__)) && ((CRYPTOPP_LLVM_CLANG_VERSION >= 30600) || \
+	    (CRYPTOPP_APPLE_CLANG_VERSION >= 70100) || (CRYPTOPP_GCC_VERSION >= 40300)))
+		#define CRYPTOPP_SECTION_INIT __attribute__((section ("__DATA,__data")))
+	#elif (defined(__ELF__) && (CRYPTOPP_GCC_VERSION >= 40300))
+		#define CRYPTOPP_SECTION_INIT __attribute__((section ("nocommon")))
+	#elif defined(__ELF__) && (defined(__xlC__) || defined(__ibmxl__))
+		#define CRYPTOPP_SECTION_INIT __attribute__((section ("nocommon")))
+	#else
+		#define CRYPTOPP_SECTION_INIT
+	#endif
+#endif
+
+// How to disable CPU feature probing. We determine machine
+// capabilities by performing an os/platform *query* first,
+// like getauxv(). If the *query* fails, we move onto a
+// cpu *probe*. The cpu *probe* tries to exeute an instruction
+// and then catches a SIGILL on Linux or the exception
+// EXCEPTION_ILLEGAL_INSTRUCTION on Windows. Some OSes
+// fail to hangle a SIGILL gracefully, like Apple OSes. Apple
+// machines corrupt memory and variables around the probe.
+#if defined(__APPLE__)
+	#define CRYPTOPP_NO_CPU_FEATURE_PROBES 1
+#endif
+
+// Flavor of inline assembly language
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief Microsoft style inline assembly
+	/// \details CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY is defined when either
+	///  <tt>_MSC_VER</tt> or <tt>__BORLANDC__</tt> are defined.
+	#define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY ...
+	/// \brief GNU style inline assembly
+	/// \details CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY is defined when neither
+	///  <tt>_MSC_VER</tt> nor <tt>__BORLANDC__</tt> are defined.
+	#define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY ...
+#elif defined(CRYPTOPP_MSC_VERSION) || defined(__BORLANDC__) || \
+	(defined(CRYPTOPP_WIN32_AVAILABLE) && defined(CRYPTOPP_LLVM_CLANG_VERSION))
+	#define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 1
+#else
+	#define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY 1
+#endif
+
+#endif  // CRYPTOPP_CONFIG_CPU_H

+ 250 - 0
include/cryptlib/config_cxx.h

@@ -0,0 +1,250 @@
+// config_cxx.h - written and placed in public domain by Jeffrey Walton
+//                the bits that make up this source file are from the
+//                library's monolithic config.h.
+
+/// \file config_cxx.h
+/// \brief Library configuration file
+/// \details <tt>config_cxx.h</tt> provides defines for C++ language and
+///  runtime library
+///  features.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_cxx.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+// Visual Studio began at VS2010, http://msdn.microsoft.com/en-us/library/hh567368%28v=vs.110%29.aspx
+//   and https://docs.microsoft.com/en-us/cpp/visual-cpp-language-conformance
+// Intel, http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler
+// GCC, http://gcc.gnu.org/projects/cxx0x.html
+// Clang, http://clang.llvm.org/cxx_status.html
+
+#ifndef CRYPTOPP_CONFIG_CXX_H
+#define CRYPTOPP_CONFIG_CXX_H
+
+#include "config_os.h"
+#include "config_cpu.h"
+#include "config_ver.h"
+
+// https://github.com/weidai11/cryptopp/issues/960
+#include <string>
+#include <exception>
+
+// You may need to force include a C++ header on Android when using STLPort
+// to ensure _STLPORT_VERSION is defined
+#if (defined(CRYPTOPP_MSC_VERSION) && CRYPTOPP_MSC_VERSION <= 1300) || \
+	defined(__MWERKS__) || \
+	(defined(_STLPORT_VERSION) && ((_STLPORT_VERSION < 0x450) || defined(_STLP_NO_UNCAUGHT_EXCEPT_SUPPORT)) || \
+	(__cplusplus >= 202002L))
+#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#endif
+
+// Ancient Crypto++ define, dating back to C++98.
+#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+# define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE 1
+# define CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION 1
+#endif
+
+// Compatibility with non-clang compilers.
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+// C++11 macro version, https://stackoverflow.com/q/7223991/608639
+#if ((CRYPTOPP_MSC_VERSION >= 1600) || (__cplusplus >= 201103L)) && !defined(_STLPORT_VERSION)
+#  define CRYPTOPP_CXX11 1
+#endif
+
+// Hack ahead. Apple's standard library does not have C++'s unique_ptr in C++11.
+// We can't test for unique_ptr directly because some of the non-Apple Clangs
+// on OS X fail the same way. However, modern standard libraries have
+// <forward_list>, so we test for it instead. Thanks to Jonathan Wakely for
+// devising the clever test for modern/ancient versions. TODO: test under
+// Xcode 3, where g++ is really g++.
+#if defined(__APPLE__) && defined(__clang__)
+#  if !(defined(__has_include) && __has_include(<forward_list>))
+#    undef CRYPTOPP_CXX11
+#  endif
+#endif
+
+// C++14 macro version, https://stackoverflow.com/q/26089319/608639
+#if defined(CRYPTOPP_CXX11) && !defined(CRYPTOPP_NO_CXX14)
+#  if ((CRYPTOPP_MSC_VERSION >= 1900) || (__cplusplus >= 201402L)) && !defined(_STLPORT_VERSION)
+#    define CRYPTOPP_CXX14 1
+#  endif
+#endif
+
+// C++17 macro version, https://stackoverflow.com/q/38456127/608639
+#if defined(CRYPTOPP_CXX14) && !defined(CRYPTOPP_NO_CXX17)
+#  if ((CRYPTOPP_MSC_VERSION >= 1900) || (__cplusplus >= 201703L)) && !defined(_STLPORT_VERSION)
+#    define CRYPTOPP_CXX17 1
+#  endif
+#endif
+
+// ***************** C++11 and above ********************
+
+#if defined(CRYPTOPP_CXX11)
+
+// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; Intel 13.0; SunCC 5.14.
+#if (CRYPTOPP_MSC_VERSION >= 1700) || __has_feature(cxx_atomic) || \
+	(__INTEL_COMPILER >= 1300) || (CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5140)
+# define CRYPTOPP_CXX11_ATOMIC 1
+#endif // atomics
+
+// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; Intel 12.0; SunCC 5.13.
+// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
+#if (CRYPTOPP_MSC_VERSION >= 1700) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || \
+	(CRYPTOPP_APPLE_CLANG_VERSION >= 50000) || (__INTEL_COMPILER >= 1200) || \
+	(CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5130)
+// Hack ahead. New GCC compilers like GCC 6 on AIX 7.0 or earlier as well as original MinGW
+// don't have the synchronization gear. However, Wakely's test used for Apple does not work
+// on the GCC/AIX combination. Another twist is we need other stuff from C++11,
+// like no-except destructors. Dumping preprocessors shows the following may
+// apply: http://stackoverflow.com/q/14191566/608639.
+# include <cstddef>
+# if !defined(__GLIBCXX__) || defined(_GLIBCXX_HAS_GTHREADS)
+#  define CRYPTOPP_CXX11_SYNCHRONIZATION 1
+# endif
+#endif // synchronization
+
+// Dynamic Initialization and Destruction with Concurrency ("Magic Statics")
+// MS at VS2015 with Vista (19.00); GCC at 4.3; LLVM Clang at 2.9; Apple Clang at 4.0; Intel 11.1; SunCC 5.13.
+// Microsoft's implementation only works for Vista and above, so its further
+// limited. http://connect.microsoft.com/VisualStudio/feedback/details/1789709
+// Clang may not support this as early as we indicate. Also see https://bugs.llvm.org/show_bug.cgi?id=47012.
+#if (__cpp_threadsafe_static_init >= 200806) || \
+	(CRYPTOPP_MSC_VERSION >= 1900) && ((WINVER >= 0x0600) || (_WIN32_WINNT >= 0x0600)) || \
+	(CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000)  || \
+	(__INTEL_COMPILER >= 1110) || (CRYPTOPP_GCC_VERSION >= 40300) || (__SUNPRO_CC >= 0x5130)
+# define CRYPTOPP_CXX11_STATIC_INIT 1
+#endif // Dynamic Initialization compilers
+
+// deleted functions: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; Intel 12.1; SunCC 5.13.
+#if (CRYPTOPP_MSC_VERSION >= 1800) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || \
+	(CRYPTOPP_APPLE_CLANG_VERSION >= 40000) || (__INTEL_COMPILER >= 1210) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__SUNPRO_CC >= 0x5130)
+# define CRYPTOPP_CXX11_DELETED_FUNCTIONS 1
+#endif // deleted functions
+
+// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.0; Intel 15.0; SunCC 5.13.
+#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_alignas) || \
+	(__INTEL_COMPILER >= 1500) || (CRYPTOPP_GCC_VERSION >= 40800) || (__SUNPRO_CC >= 0x5130)
+#  define CRYPTOPP_CXX11_ALIGNAS 1
+#endif // alignas
+
+// alignof: MS at VS2015 (19.00); GCC at 4.5; Clang at 2.9; Intel 15.0; SunCC 5.13.
+#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_alignof) || \
+	(__INTEL_COMPILER >= 1500) || (CRYPTOPP_GCC_VERSION >= 40500) || (__SUNPRO_CC >= 0x5130)
+#  define CRYPTOPP_CXX11_ALIGNOF 1
+#endif // alignof
+
+// initializer lists: MS at VS2013 (18.00); GCC at 4.4; Clang at 3.1; Intel 14.0; SunCC 5.13.
+#if (CRYPTOPP_MSC_VERSION >= 1800) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30100) || \
+	(CRYPTOPP_APPLE_CLANG_VERSION >= 40000) || (__INTEL_COMPILER >= 1400) || \
+	(CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5130)
+#  define CRYPTOPP_CXX11_INITIALIZER_LIST 1
+#endif // alignas
+
+// lambdas: MS at VS2012 (17.00); GCC at 4.9; Clang at 3.3; Intel 12.0; SunCC 5.14.
+#if (CRYPTOPP_MSC_VERSION >= 1700) || __has_feature(cxx_lambdas) || \
+	(__INTEL_COMPILER >= 1200) || (CRYPTOPP_GCC_VERSION >= 40900) || (__SUNPRO_CC >= 0x5140)
+#  define CRYPTOPP_CXX11_LAMBDA 1
+#endif // lambdas
+
+// noexcept: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 14.0; SunCC 5.13.
+#if (CRYPTOPP_MSC_VERSION >= 1900) || __has_feature(cxx_noexcept) || \
+	(__INTEL_COMPILER >= 1400) || (CRYPTOPP_GCC_VERSION >= 40600) || (__SUNPRO_CC >= 0x5130)
+# define CRYPTOPP_CXX11_NOEXCEPT 1
+#endif // noexcept compilers
+
+// variadic templates: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; Intel 12.1; SunCC 5.13.
+#if (__cpp_variadic_templates >= 200704) || __has_feature(cxx_variadic_templates) || \
+	(CRYPTOPP_MSC_VERSION >= 1800) || (__INTEL_COMPILER >= 1210) || \
+	(CRYPTOPP_GCC_VERSION >= 40300) || (__SUNPRO_CC >= 0x5130)
+# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
+#endif // variadic templates
+
+// constexpr: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.1; Intel 16.0; SunCC 5.13.
+// Intel has mis-supported the feature since at least ICPC 13.00
+#if (__cpp_constexpr >= 200704) || __has_feature(cxx_constexpr) || \
+	(CRYPTOPP_MSC_VERSION >= 1900) || (__INTEL_COMPILER >= 1600) || \
+	(CRYPTOPP_GCC_VERSION >= 40600) || (__SUNPRO_CC >= 0x5130)
+# define CRYPTOPP_CXX11_CONSTEXPR 1
+#endif // constexpr compilers
+
+// strong typed enums: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Intel 14.0; SunCC 5.12.
+// Mircorosft and Intel had partial support earlier, but we require full support.
+#if (CRYPTOPP_MSC_VERSION >= 1700) || __has_feature(cxx_strong_enums) || \
+	(__INTEL_COMPILER >= 1400) || (CRYPTOPP_GCC_VERSION >= 40400) || (__SUNPRO_CC >= 0x5120)
+# define CRYPTOPP_CXX11_STRONG_ENUM 1
+#endif // constexpr compilers
+
+// nullptr_t: MS at VS2010 (16.00); GCC at 4.6; Clang at 3.3; Intel 10.0; SunCC 5.13.
+#if (CRYPTOPP_MSC_VERSION >= 1600) || __has_feature(cxx_nullptr) || \
+	(__INTEL_COMPILER >= 1000) || (CRYPTOPP_GCC_VERSION >= 40600) || \
+    (__SUNPRO_CC >= 0x5130) || defined(__IBMCPP_NULLPTR)
+# define CRYPTOPP_CXX11_NULLPTR 1
+#endif // nullptr_t compilers
+
+#endif // CRYPTOPP_CXX11
+
+// ***************** C++14 and above ********************
+
+#if defined(CRYPTOPP_CXX14)
+
+// Extended static_assert with one argument
+// Microsoft cannot handle the single argument static_assert as of VS2019 (cl.exe 19.00)
+#if (__cpp_static_assert >= 201411)
+# define CRYPTOPP_CXX17_STATIC_ASSERT 1
+#endif // static_assert
+
+#endif
+
+// ***************** C++17 and above ********************
+
+// C++17 is available
+#if defined(CRYPTOPP_CXX17)
+
+// C++17 uncaught_exceptions: MS at VS2015 (19.00); GCC at 6.0; Clang at 3.5; Intel 18.0.
+// Clang and __EXCEPTIONS see http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html
+// Also see https://github.com/weidai11/cryptopp/issues/980. I'm not sure what
+// to do when the compiler defines __cpp_lib_uncaught_exceptions but the platform
+// does not support std::uncaught_exceptions. What was Apple thinking???
+#if defined(__clang__)
+# if __EXCEPTIONS && __has_feature(cxx_exceptions)
+#  if __cpp_lib_uncaught_exceptions >= 201411L
+#   define CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS 1
+#  endif
+# endif
+#elif (CRYPTOPP_MSC_VERSION >= 1900) || (__INTEL_COMPILER >= 1800) || \
+      (CRYPTOPP_GCC_VERSION >= 60000) || (__cpp_lib_uncaught_exceptions >= 201411L)
+# define CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS 1
+#endif // uncaught_exceptions compilers
+
+#endif  // CRYPTOPP_CXX17
+
+// ***************** C++ fixups ********************
+
+#if defined(CRYPTOPP_CXX11_NOEXCEPT)
+#  define CRYPTOPP_THROW noexcept(false)
+#  define CRYPTOPP_NO_THROW noexcept(true)
+#else
+#  define CRYPTOPP_THROW
+#  define CRYPTOPP_NO_THROW
+#endif // CRYPTOPP_CXX11_NOEXCEPT
+
+// Hack... C++11 nullptr_t type safety and analysis
+#if defined(CRYPTOPP_CXX11_NULLPTR) && !defined(NULLPTR)
+# define NULLPTR nullptr
+#elif !defined(NULLPTR)
+# define NULLPTR NULL
+#endif // CRYPTOPP_CXX11_NULLPTR
+
+#endif  // CRYPTOPP_CONFIG_CXX_H

+ 178 - 0
include/cryptlib/config_dll.h

@@ -0,0 +1,178 @@
+// config_dll.h - written and placed in public domain by Jeffrey Walton
+//                the bits that make up this source file are from the
+//                library's monolithic config.h.
+
+/// \file config_dll.h
+/// \brief Library configuration file
+/// \details <tt>config_dll.h</tt> provides defines for shared objects and
+///  dynamic libraries. Generally speaking the macros are used to export
+///  classes and template classes from the Win32 dynamic link library.
+///  When not building the Win32 dynamic link library they are mostly an extern
+///  template declaration.
+/// \details In practice they are a furball coughed up by a cat and then peed
+///  on by a dog. They are awful to get just right because of inconsistent
+///  compiler support for extern templates, manual instantiation and the FIPS DLL.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_dll.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_DLL_H
+#define CRYPTOPP_CONFIG_DLL_H
+
+#include "config_os.h"
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+	/// \brief Win32 define for dynamic link libraries
+	/// \details CRYPTOPP_IMPORTS is set in the Visual Studio project files.
+	///  When the macro is set, <tt>CRYPTOPP_DLL</tt> is defined to
+	///  <tt>__declspec(dllimport)</tt>.
+	/// \details This macro has no effect on Unix &amp; Linux.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_IMPORTS ...
+
+	/// \brief Win32 define for dynamic link libraries
+	/// \details CRYPTOPP_EXPORTS is set in the Visual Studio project files.
+	///  When the macro is set, <tt>CRYPTOPP_DLL</tt> is defined to
+	///  <tt>__declspec(dllexport)</tt>.
+	/// \details This macro has no effect on Unix &amp; Linux.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_EXPORTS ...
+
+	/// \brief Win32 define for dynamic link libraries
+	/// \details CRYPTOPP_IS_DLL is set in the Visual Studio project files.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_IS_DLL
+
+	/// \brief Instantiate templates in a dynamic library
+	/// \details CRYPTOPP_DLL_TEMPLATE_CLASS decoration should be used
+	///  for classes intended to be exported from dynamic link libraries.
+	/// \details This macro is primarily used on Win32, but sees some
+	///  action on Unix &amp; Linux due to the source file <tt>dll.cpp</tt>.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_DLL_TEMPLATE_CLASS ...
+
+	/// \brief Instantiate templates in a dynamic library
+	/// \details CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS decoration should be used
+	///  for template classes intended to be exported from dynamic link libraries.
+	/// \details This macro is primarily used on Win32, but sees some
+	///  action on Unix &amp; Linux due to the source file <tt>dll.cpp</tt>.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS ...
+
+	/// \brief Instantiate templates in a dynamic library
+	/// \details CRYPTOPP_STATIC_TEMPLATE_CLASS decoration should be used
+	///  for template classes intended to be exported from dynamic link libraries.
+	/// \details This macro is primarily used on Win32, but sees some
+	///  action on Unix &amp; Linux due to the source file <tt>dll.cpp</tt>.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_STATIC_TEMPLATE_CLASS ...
+
+	/// \brief Instantiate templates in a dynamic library
+	/// \details CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS decoration should be used
+	///  for template classes intended to be exported from dynamic link libraries.
+	/// \details This macro is primarily used on Win32, but sees some
+	///  action on Unix &amp; Linux due to the source file <tt>dll.cpp</tt>.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>,
+	///  and <A HREF="https://www.cryptopp.com/wiki/FIPS_DLL">FIPS DLL</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS ...
+
+	/// \brief Override for internal linkage
+	/// \details CRYPTOPP_TABLE can be used to override internal linkage
+	///  on tables with the <tt>const</tt> qualifier. According to C++ rules
+	///  a declaration with <tt>const</tt> qualifier is internal linkage.
+	/// \note The name CRYPTOPP_TABLE was chosen because it is often used to
+	///  export a table, like AES or SHA constants. The name avoids collisions
+	///  with the DLL gear macros, like CRYPTOPP_EXPORTS and CRYPTOPP_EXTERN.
+	#define CRYPTOPP_TABLE extern
+
+	/// \brief Win32 calling convention
+	/// \details CRYPTOPP_API sets the calling convention on Win32.
+	///  On Win32 CRYPTOPP_API is <tt>__cedcl</tt>. On Unix &amp; Linux
+	///  CRYPTOPP_API is defined to nothing.
+	/// \sa <A HREF="https://www.cryptopp.com/wiki/Visual_Studio">Visual Studio</A>
+	///  on the Crypto++ wiki
+	#define CRYPTOPP_API ...
+
+#else  // CRYPTOPP_DOXYGEN_PROCESSING
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE)
+
+	#if defined(CRYPTOPP_EXPORTS)
+	#  define CRYPTOPP_IS_DLL
+	#  define CRYPTOPP_DLL __declspec(dllexport)
+	#elif defined(CRYPTOPP_IMPORTS)
+	#  define CRYPTOPP_IS_DLL
+	#  define CRYPTOPP_DLL __declspec(dllimport)
+	#else
+	#  define CRYPTOPP_DLL
+	#endif
+
+	// C++ makes const internal linkage
+	#define CRYPTOPP_TABLE extern
+	#define CRYPTOPP_API __cdecl
+
+#else	// not CRYPTOPP_WIN32_AVAILABLE
+
+	// C++ makes const internal linkage
+	#define CRYPTOPP_TABLE extern
+	#define CRYPTOPP_DLL
+	#define CRYPTOPP_API
+
+#endif	// CRYPTOPP_WIN32_AVAILABLE
+
+#if defined(__MWERKS__)
+#  define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#  define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#  define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
+#  define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#  define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
+#endif
+
+#if defined(__MWERKS__)
+#  define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#  define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
+#else
+#  define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
+#  define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
+#else
+#  define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
+#endif
+
+#endif  // CRYPTOPP_DOXYGEN_PROCESSING
+
+#endif  // CRYPTOPP_CONFIG_DLL_H

+ 268 - 0
include/cryptlib/config_int.h

@@ -0,0 +1,268 @@
+// config_int.h - written and placed in public domain by Jeffrey Walton
+//                the bits that make up this source file are from the
+//                library's monolithic config.h.
+
+/// \file config_int.h
+/// \brief Library configuration file
+/// \details <tt>config_int.h</tt> provides defines and typedefs for fixed
+///  size integers. The library's choices for fixed size integers predates other
+///  standard-based integers by about 5 years. After fixed sizes were
+///  made standard, the library continued to use its own definitions for
+///  compatibility with previous versions of the library.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_int.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_INT_H
+#define CRYPTOPP_CONFIG_INT_H
+
+#include "config_ns.h"
+#include "config_ver.h"
+#include "config_misc.h"
+
+// C5264 new for VS2022/v17.4, MSC v17.3.4
+// https://github.com/weidai11/cryptopp/issues/1185
+#if (CRYPTOPP_MSC_VERSION)
+# pragma warning(push)
+# if (CRYPTOPP_MSC_VERSION >= 1933)
+#  pragma warning(disable: 5264)
+# endif
+#endif
+
+/// \brief Library byte guard
+/// \details CRYPTOPP_NO_GLOBAL_BYTE indicates <tt>byte</tt> is in the Crypto++
+///  namespace.
+/// \details The Crypto++ <tt>byte</tt> was originally in global namespace to avoid
+///  ambiguity with other byte typedefs. <tt>byte</tt> was moved to CryptoPP namespace
+///  at Crypto++ 6.0 due to C++17, <tt>std::byte</tt> and potential compile problems.
+/// \sa <A HREF="http://github.com/weidai11/cryptopp/issues/442">Issue 442</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">std::byte</A> on the
+///  Crypto++ wiki
+/// \since Crypto++ 6.0
+#define CRYPTOPP_NO_GLOBAL_BYTE 1
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// Signed words added at Issue 609 for early versions of and Visual Studio and
+// the NaCl gear. Also see https://github.com/weidai11/cryptopp/issues/609.
+
+/// \brief 8-bit unsigned datatype
+/// \details The Crypto++ <tt>byte</tt> was originally in global namespace to avoid
+///  ambiguity with other byte typedefs. <tt>byte</tt> was moved to CryptoPP namespace
+///  at Crypto++ 6.0 due to C++17, <tt>std::byte</tt> and potential compile problems.
+/// \sa CRYPTOPP_NO_GLOBAL_BYTE, <A HREF="http://github.com/weidai11/cryptopp/issues/442">Issue 442</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">std::byte</A> on the
+///  Crypto++ wiki
+/// \since Crypto++ 1.0, CryptoPP namespace since Crypto++ 6.0
+typedef unsigned char byte;
+/// \brief 16-bit unsigned datatype
+/// \since Crypto++ 1.0
+typedef unsigned short word16;
+/// \brief 32-bit unsigned datatype
+/// \since Crypto++ 1.0
+typedef unsigned int word32;
+
+/// \brief 8-bit signed datatype
+/// \details The 8-bit signed datatype was added to support constant time
+///  implementations for curve25519, X25519 key agreement and ed25519
+///  signatures.
+/// \since Crypto++ 8.0
+typedef signed char sbyte;
+/// \brief 16-bit signed datatype
+/// \details The 32-bit signed datatype was added to support constant time
+///  implementations for curve25519, X25519 key agreement and ed25519
+///  signatures.
+/// \since Crypto++ 8.0
+typedef signed short sword16;
+/// \brief 32-bit signed datatype
+/// \details The 32-bit signed datatype was added to support constant time
+///  implementations for curve25519, X25519 key agreement and ed25519
+///  signatures.
+/// \since Crypto++ 8.0
+typedef signed int sword32;
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+	/// \brief 64-bit unsigned datatype
+	/// \details The typedef for <tt>word64</tt> varies depending on the platform.
+	///  On Microsoft platforms it is <tt>unsigned __int64</tt>. On Unix &amp; Linux
+	///  with LP64 data model it is <tt>unsigned long</tt>. On Unix &amp; Linux with ILP32
+	///  data model it is <tt>unsigned long long</tt>.
+	/// \since Crypto++ 1.0
+	typedef unsigned long long word64;
+
+	/// \brief 64-bit signed datatype
+	/// \details The typedef for <tt>sword64</tt> varies depending on the platform.
+	///  On Microsoft platforms it is <tt>signed __int64</tt>. On Unix &amp; Linux
+	///  with LP64 data model it is <tt>signed long</tt>. On Unix &amp; Linux with ILP32
+	///  data model it is <tt>signed long long</tt>.
+	/// \since Crypto++ 8.0
+	typedef signed long long sword64;
+
+	/// \brief 128-bit unsigned datatype
+	/// \details The typedef for <tt>word128</tt> varies depending on the platform.
+	///  <tt>word128</tt> is only available on 64-bit machines when
+	///  <tt>CRYPTOPP_WORD128_AVAILABLE</tt> is defined.
+	///  On Unix &amp; Linux with LP64 data model it is <tt>__uint128_t</tt>.
+	///  Microsoft platforms do not provide a 128-bit integer type. 32-bit platforms
+	///  do not provide a 128-bit integer type.
+	/// \since Crypto++ 5.6
+	typedef __uint128_t word128;
+
+	/// \brief Declare an unsigned word64
+	/// \details W64LIT is used to portability declare or assign 64-bit literal values.
+	///  W64LIT will append the proper suffix to ensure the compiler accepts the literal.
+	/// \details Use the macro like shown below.
+	///  <pre>
+	///    word64 x = W64LIT(0xffffffffffffffff);
+	///  </pre>
+	/// \since Crypto++ 1.0
+	#define W64LIT(x) ...
+
+	/// \brief Declare a signed word64
+	/// \details SW64LIT is used to portability declare or assign 64-bit literal values.
+	///  SW64LIT will append the proper suffix to ensure the compiler accepts the literal.
+	/// \details Use the macro like shown below.
+	///  <pre>
+	///    sword64 x = SW64LIT(0xffffffffffffffff);
+	///  </pre>
+	/// \since Crypto++ 8.0
+	#define SW64LIT(x) ...
+
+	/// \brief Declare ops on word64 are slow
+	/// \details CRYPTOPP_BOOL_SLOW_WORD64 is typically defined to 1 on platforms
+	///  that have a machine word smaller than 64-bits. That is, the define
+	///  is present on 32-bit platforms. The define is also present on platforms
+	///  where the cpu is slow even with a 64-bit cpu.
+	#define CRYPTOPP_BOOL_SLOW_WORD64 ...
+
+#elif defined(CRYPTOPP_MSC_VERSION) || defined(__BORLANDC__)
+	typedef signed __int64 sword64;
+	typedef unsigned __int64 word64;
+	#define SW64LIT(x) x##i64
+	#define W64LIT(x) x##ui64
+#elif (_LP64 || __LP64__)
+	typedef signed long sword64;
+	typedef unsigned long word64;
+	#define SW64LIT(x) x##L
+	#define W64LIT(x) x##UL
+#else
+	typedef signed long long sword64;
+	typedef unsigned long long word64;
+	#define SW64LIT(x) x##LL
+	#define W64LIT(x) x##ULL
+#endif
+
+/// \brief Large word type
+/// \details lword is a typedef for large word types. It is used for file
+///  offsets and such.
+typedef word64 lword;
+
+/// \brief Large word type max value
+/// \details LWORD_MAX is the maximum value for large word types.
+///  Since an <tt>lword</tt> is an unsigned type, the value is
+///  <tt>0xffffffffffffffff</tt>. W64LIT will append the proper suffix.
+CRYPTOPP_CONST_OR_CONSTEXPR lword LWORD_MAX = W64LIT(0xffffffffffffffff);
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+	/// \brief Half word used for multiprecision integer arithmetic
+	/// \details hword is used for multiprecision integer arithmetic.
+	///  The typedef for <tt>hword</tt> varies depending on the platform.
+	///  On 32-bit platforms it is usually <tt>word16</tt>. On 64-bit platforms
+	///  it is usually <tt>word32</tt>.
+	/// \details Library users typically use byte, word16, word32 and word64.
+	/// \since Crypto++ 2.0
+	typedef word32 hword;
+	/// \brief Full word used for multiprecision integer arithmetic
+	/// \details word is used for multiprecision integer arithmetic.
+	///  The typedef for <tt>word</tt> varies depending on the platform.
+	///  On 32-bit platforms it is usually <tt>word32</tt>. On 64-bit platforms
+	///  it is usually <tt>word64</tt>.
+	/// \details Library users typically use byte, word16, word32 and word64.
+	/// \since Crypto++ 2.0
+	typedef word64 word;
+	/// \brief Double word used for multiprecision integer arithmetic
+	/// \details dword is used for multiprecision integer arithmetic.
+	///  The typedef for <tt>dword</tt> varies depending on the platform.
+	///  On 32-bit platforms it is usually <tt>word64</tt>. On 64-bit Unix &amp;
+	///  Linux platforms it is usually <tt>word128</tt>. <tt>word128</tt> is
+	///  not available on Microsoft platforms. <tt>word128</tt> is only available
+	///  when <tt>CRYPTOPP_WORD128_AVAILABLE</tt> is defined.
+	/// \details Library users typically use byte, word16, word32 and word64.
+	/// \sa CRYPTOPP_WORD128_AVAILABLE
+	/// \since Crypto++ 2.0
+	typedef word128 dword;
+
+	/// \brief 128-bit word availability
+	/// \details CRYPTOPP_WORD128_AVAILABLE indicates a 128-bit word is
+	///  available from the platform. 128-bit words are usually available on
+	///  64-bit platforms, but not available 32-bit platforms.
+	/// \details If CRYPTOPP_WORD128_AVAILABLE is not defined, then 128-bit
+	///  words are not available.
+	/// \details GCC and compatible compilers signal 128-bit word availability
+	///  with the preporcessor macro <tt>__SIZEOF_INT128__ >= 16</tt>.
+	/// \since Crypto++ 2.0
+	#define CRYPTOPP_WORD128_AVAILABLE ...
+#else
+	// define hword, word, and dword. these are used for multiprecision integer arithmetic
+	// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
+	#if (defined(CRYPTOPP_MSC_VERSION) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
+		typedef word32 hword;
+		typedef word64 word;
+	#else
+		#define CRYPTOPP_NATIVE_DWORD_AVAILABLE 1
+		#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__) || defined(__aarch64__)
+			#if ((CRYPTOPP_GCC_VERSION >= 30400) || (CRYPTOPP_LLVM_CLANG_VERSION >= 30000) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40300)) && (__SIZEOF_INT128__ >= 16)
+				// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
+				// GCC 4.8.3 and bad uint128_t ops on PPC64/POWER7 (Issue 421)
+				// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
+				typedef word32 hword;
+				typedef word64 word;
+				typedef __uint128_t dword;
+				typedef __uint128_t word128;
+				#define CRYPTOPP_WORD128_AVAILABLE 1
+			#else
+				// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
+				typedef word16 hword;
+				typedef word32 word;
+				typedef word64 dword;
+			#endif
+		#else
+			// being here means the native register size is probably 32 bits or less
+			#define CRYPTOPP_BOOL_SLOW_WORD64 1
+			typedef word16 hword;
+			typedef word32 word;
+			typedef word64 dword;
+		#endif
+	#endif
+#endif
+
+#ifndef CRYPTOPP_BOOL_SLOW_WORD64
+# define CRYPTOPP_BOOL_SLOW_WORD64 0
+#endif
+
+/// \brief Size of a platform word in bytes
+/// \details The size of a platform word, in bytes
+CRYPTOPP_CONST_OR_CONSTEXPR unsigned int WORD_SIZE = sizeof(word);
+
+/// \brief Size of a platform word in bits
+/// \details The size of a platform word, in bits
+/// \sa https://github.com/weidai11/cryptopp/issues/1185
+CRYPTOPP_CONST_OR_CONSTEXPR unsigned int WORD_BITS = WORD_SIZE * 8;
+
+NAMESPACE_END
+
+#if (CRYPTOPP_MSC_VERSION)
+# pragma warning(pop)
+#endif
+
+#endif  // CRYPTOPP_CONFIG_INT_H

+ 199 - 0
include/cryptlib/config_misc.h

@@ -0,0 +1,199 @@
+// config_misc.h - written and placed in public domain by Jeffrey Walton
+//                 the bits that make up this source file are from the
+//                 library's monolithic config.h.
+
+/// \file config_misc.h
+/// \brief Library configuration file
+/// \details <tt>config_misc.h</tt> provides miscellaneous defines.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_misc.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_MISC_H
+#define CRYPTOPP_CONFIG_MISC_H
+
+#include "config_asm.h"
+#include "config_cxx.h"
+#include "config_os.h"
+#include "config_ver.h"
+
+// Define this if running on a big-endian CPU
+// big endian will be assumed if CRYPTOPP_LITTLE_ENDIAN is not non-0
+#if !defined(CRYPTOPP_LITTLE_ENDIAN) && !defined(CRYPTOPP_BIG_ENDIAN) && (defined(__BIG_ENDIAN__) || (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || (defined(__m68k__) || defined(__MC68K__)) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
+#	define CRYPTOPP_BIG_ENDIAN 1
+#endif
+
+// Define this if running on a little-endian CPU
+// big endian will be assumed if CRYPTOPP_LITTLE_ENDIAN is not non-0
+#if !defined(CRYPTOPP_BIG_ENDIAN) && !defined(CRYPTOPP_LITTLE_ENDIAN)
+#	define CRYPTOPP_LITTLE_ENDIAN 1
+#endif
+
+// Define this if you want to set a prefix for TestData/ and TestVectors/
+// Be sure to add the trailing slash since its simple concatenation.
+// After https://github.com/weidai11/cryptopp/issues/760 the library
+// should find the test vectors and data without much effort. It
+// will search in "./" and "$ORIGIN/../share/cryptopp" automatically.
+#ifndef CRYPTOPP_DATA_DIR
+# define CRYPTOPP_DATA_DIR ""
+#endif
+
+// Define this to disable the test suite from searching for test
+// vectors and data in "./" and "$ORIGIN/../share/cryptopp". The
+// library will still search in CRYPTOPP_DATA_DIR, regardless.
+// Some distros may want to disable this feature. Also see
+// https://github.com/weidai11/cryptopp/issues/760
+// #ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
+// # define CRYPTOPP_DISABLE_DATA_DIR_SEARCH
+// #endif
+
+// Define this if you want or need the library's memcpy_s and memmove_s.
+// See http://github.com/weidai11/cryptopp/issues/28.
+// #if !defined(CRYPTOPP_WANT_SECURE_LIB)
+// # define CRYPTOPP_WANT_SECURE_LIB
+// #endif
+
+// Define this if ARMv8 shifts are slow. ARM Cortex-A53 and Cortex-A57 shift
+// operation perform poorly, so NEON and ASIMD code that relies on shifts
+// or rotates often performs worse than C/C++ code. Also see
+// http://github.com/weidai11/cryptopp/issues/367.
+#define CRYPTOPP_SLOW_ARMV8_SHIFT 1
+
+// CRYPTOPP_DEBUG enables the library's CRYPTOPP_ASSERT. CRYPTOPP_ASSERT
+// raises a SIGTRAP (Unix) or calls DebugBreak() (Windows). CRYPTOPP_ASSERT
+// is only in effect when CRYPTOPP_DEBUG, DEBUG or _DEBUG is defined. Unlike
+// Posix assert, CRYPTOPP_ASSERT is not affected by NDEBUG (or failure to
+// define it). According to the ndk-build docs, Android use NDK_DEBUG=1 to
+// signal a DEBUG build (and NDK_DEBUG=0 to signal non-DEBUG build).
+// Also see http://github.com/weidai11/cryptopp/issues/277, CVE-2016-7420 and
+// https://developer.android.com/ndk/guides/ndk-build
+#if (defined(DEBUG) || defined(_DEBUG)) || (defined(NDK_DEBUG) && (NDK_DEBUG > 0))
+# undef CRYPTOPP_DEBUG
+# define CRYPTOPP_DEBUG 1
+#endif
+
+// File system code to use when creating GZIP archive.
+// http://www.gzip.org/format.txt
+#if !defined(GZIP_OS_CODE)
+# if defined(__macintosh__)
+#  define GZIP_OS_CODE 7
+# elif defined(__unix__) || defined(__linux__)
+#  define GZIP_OS_CODE 3
+# else
+#  define GZIP_OS_CODE 0
+# endif
+#endif
+
+// Try this if your CPU has 256K internal cache or a slow multiply instruction
+// and you want a (possibly) faster IDEA implementation using log tables
+// #define IDEA_LARGECACHE
+
+// Define this if, for the linear congruential RNG, you want to use
+// the original constants as specified in S.K. Park and K.W. Miller's
+// CACM paper.
+// #define LCRNG_ORIGINAL_NUMBERS
+
+// Define this if you want Integer's operator<< to honor std::showbase (and
+// std::noshowbase). If defined, Integer will use a suffix of 'b', 'o', 'h'
+// or '.' (the last for decimal) when std::showbase is in effect. If
+// std::noshowbase is set, then the suffix is not added to the Integer. If
+// not defined, existing behavior is preserved and Integer will use a suffix
+// of 'b', 'o', 'h' or '.' (the last for decimal).
+// #define CRYPTOPP_USE_STD_SHOWBASE
+
+// Define this if you want to decouple AlgorithmParameters and Integer
+// The decoupling should make it easier for the linker to remove Integer
+// related code for those who do not need Integer, and avoid a potential
+// race during AssignIntToInteger pointer initialization. Also
+// see http://github.com/weidai11/cryptopp/issues/389.
+// #define CRYPTOPP_NO_ASSIGN_TO_INTEGER
+
+// Need GCC 4.6/Clang 1.7/Apple Clang 2.0 or above due to "GCC diagnostic {push|pop}"
+#if (CRYPTOPP_GCC_VERSION >= 40600) || (CRYPTOPP_LLVM_CLANG_VERSION >= 10700) || \
+    (CRYPTOPP_APPLE_CLANG_VERSION >= 20000)
+	#define CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE 1
+#endif
+
+// Portable way to suppress warnings.
+// Moved from misc.h due to circular depenedencies.
+#ifndef CRYPTOPP_UNUSED
+	#define CRYPTOPP_UNUSED(x) ((void)(x))
+#endif
+
+// how to disable inlining
+#if defined(CRYPTOPP_MSC_VERSION)
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT
+#	define CRYPTOPP_NOINLINE __declspec(noinline)
+#elif defined(__xlc__) || defined(__xlC__) || defined(__ibmxl__)
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT ...
+#	define CRYPTOPP_NOINLINE __attribute__((noinline))
+#elif defined(__GNUC__)
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT
+#	define CRYPTOPP_NOINLINE __attribute__((noinline))
+#else
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT ...
+#	define CRYPTOPP_NOINLINE
+#endif
+
+// http://stackoverflow.com/a/13867690/608639
+// CRYPTOPP_CONST_OR_CONSTEXPR due to https://github.com/weidai11/cryptopp/issues/1185
+#if defined(CRYPTOPP_CXX11_CONSTEXPR)
+#  define CRYPTOPP_STATIC_CONSTEXPR static constexpr
+#  define CRYPTOPP_STATIC_CONST_OR_CONSTEXPR static constexpr
+#  define CRYPTOPP_CONST_OR_CONSTEXPR constexpr
+#  define CRYPTOPP_CONSTEXPR constexpr
+#else
+#  define CRYPTOPP_STATIC_CONSTEXPR static
+#  define CRYPTOPP_STATIC_CONST_OR_CONSTEXPR static const
+#  define CRYPTOPP_CONST_OR_CONSTEXPR const
+#  define CRYPTOPP_CONSTEXPR
+#endif // CRYPTOPP_CXX11_CONSTEXPR
+
+#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
+# define CRYPTOPP_CONSTANT(x) static const int x
+#elif defined(CRYPTOPP_CXX11_STRONG_ENUM)
+# define CRYPTOPP_CONSTANT(x) enum : int { x }
+#elif defined(CRYPTOPP_CXX11_CONSTEXPR)
+# define CRYPTOPP_CONSTANT(x) constexpr static int x
+#else
+# define CRYPTOPP_CONSTANT(x) static const int x
+#endif
+
+// Warnings
+#ifdef CRYPTOPP_MSC_VERSION
+	// 4127: conditional expression is constant
+	// 4512: assignment operator not generated
+	// 4661: no suitable definition provided for explicit template instantiation request
+	// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
+#	pragma warning(disable: 4127 4512 4661 4910)
+	// CRYPTOPP_MSC_VERSION 1920 is VS2019
+#	if CRYPTOPP_MSC_VERSION >= 1920
+		// 5054: operator '|': deprecated between enumerations of different types
+#		pragma warning(disable: 5054)
+#	endif
+	// Security related, possible defects
+	// http://blogs.msdn.com/b/vcblog/archive/2010/12/14/off-by-default-compiler-warnings-in-visual-c.aspx
+#	pragma warning(once: 4191 4242 4263 4264 4266 4302 4826 4905 4906 4928)
+#endif
+
+#ifdef __BORLANDC__
+// 8037: non-const function called for const object. needed to work around BCB2006 bug
+#	pragma warn -8037
+#endif
+
+// [GCC Bug 53431] "C++ preprocessor ignores #pragma GCC diagnostic". Clang honors it.
+#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic ignored "-Wunknown-pragmas"
+# pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#endif  // CRYPTOPP_CONFIG_MISC_H

+ 76 - 0
include/cryptlib/config_ns.h

@@ -0,0 +1,76 @@
+// config_ns.h - written and placed in public domain by Jeffrey Walton
+//               the bits that make up this source file are from the
+//               library's monolithic config.h.
+
+/// \file config_ns.h
+/// \brief Library configuration file
+/// \details <tt>config_ns.h</tt> provides defines for C++ and library
+///  namespaces.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_ns.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_NAMESPACE_H
+#define CRYPTOPP_CONFIG_NAMESPACE_H
+
+// namespace support is now required
+#ifdef NO_NAMESPACE
+# error namespace support is now required
+#endif
+
+#ifdef CRYPTOPP_DOXYGEN_PROCESSING
+
+/// \namespace CryptoPP
+/// \brief Crypto++ library namespace
+/// \details Nearly all classes are located in the CryptoPP namespace. Within
+///  the namespace, there are four additional namespaces.
+///   <ul>
+///     <li>Name - namespace for names used with NameValuePairs and documented
+///         in argnames.h
+///     <li>NaCl - namespace for NaCl test functions like crypto_box,
+///         crypto_box_open, crypto_sign, and crypto_sign_open
+///     <li>Donna - namespace for curve25519 library operations. The name was
+///         selected due to use of Langley and Moon's curve25519-donna.
+///     <li>Test - namespace for testing and benchmarks classes
+///     <li>Weak - namespace for weak and wounded algorithms, like ARC4, MD5
+///         and Pananma
+///   </ul>
+/// \since Crypto++ 3.0
+namespace CryptoPP { }
+
+// Bring in the symbols found in the weak namespace; and fold Weak1 into Weak
+#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
+#define Weak1 Weak
+// Avoid putting "CryptoPP::" in front of everything in Doxygen output
+#define CryptoPP
+#define NAMESPACE_BEGIN(x)
+#define NAMESPACE_END
+// Get Doxygen to generate better documentation for these typedefs
+#define DOCUMENTED_TYPEDEF(x, y) class y : public x {}
+// Make "protected" "private" so the functions and members are not documented
+#define protected private
+
+#else
+// Not Doxygen
+#define NAMESPACE_BEGIN(x) namespace x {
+#define NAMESPACE_END }
+#define DOCUMENTED_TYPEDEF(x, y) typedef x y
+
+#endif  // CRYPTOPP_DOXYGEN_PROCESSING
+
+#define ANONYMOUS_NAMESPACE_BEGIN namespace {
+#define ANONYMOUS_NAMESPACE_END }
+#define USING_NAMESPACE(x) using namespace x;
+#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
+#define DOCUMENTED_NAMESPACE_END }
+
+#endif  // CRYPTOPP_CONFIG_NAMESPACE_H

+ 168 - 0
include/cryptlib/config_os.h

@@ -0,0 +1,168 @@
+// config_os.h - written and placed in public domain by Jeffrey Walton
+//               the bits that make up this source file are from the
+//               library's monolithic config.h.
+
+/// \file config_os.h
+/// \brief Library configuration file
+/// \details <tt>config_os.h</tt> provides defines for platforms and operating
+///  systems.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_os.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_OS_H
+#define CRYPTOPP_CONFIG_OS_H
+
+#include "config_ver.h"
+
+// It is OK to remove the hard stop below, but you are on your own.
+// After building the library be sure to run self tests described
+// https://www.cryptopp.com/wiki/Release_Process#Self_Tests
+// The problems with Clang pretending to be other compilers is
+// discussed at http://github.com/weidai11/cryptopp/issues/147.
+#if (defined(_MSC_VER) && defined(__clang__))
+# error: "Unsupported configuration"
+#endif
+
+// Windows platform
+#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
+#define CRYPTOPP_WIN32_AVAILABLE
+#endif
+
+// Unix and Linux platforms
+#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
+#define CRYPTOPP_UNIX_AVAILABLE
+#endif
+
+// BSD platforms
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#define CRYPTOPP_BSD_AVAILABLE
+#endif
+
+// Microsoft compilers
+#if defined(CRYPTOPP_MSC_VERSION) || defined(__fastcall)
+	#define CRYPTOPP_FASTCALL __fastcall
+#else
+	#define CRYPTOPP_FASTCALL
+#endif
+
+// Microsoft compilers
+#if defined(CRYPTOPP_MSC_VERSION)
+	#define CRYPTOPP_NO_VTABLE __declspec(novtable)
+#else
+	#define CRYPTOPP_NO_VTABLE
+#endif
+
+// Define this if you want to disable all OS-dependent features,
+// such as sockets and OS-provided random number generators
+// #define NO_OS_DEPENDENCE
+
+// Define this to use features provided by Microsoft's CryptoAPI.
+// Currently the only feature used is Windows random number generation.
+// This macro will be ignored if NO_OS_DEPENDENCE is defined.
+// #define USE_MS_CRYPTOAPI
+
+// Define this to use features provided by Microsoft's CryptoNG API.
+// CryptoNG API is available in Vista and above and its cross platform,
+// including desktop apps and store apps. Currently the only feature
+// used is Windows random number generation.
+// This macro will be ignored if NO_OS_DEPENDENCE is defined.
+// #define USE_MS_CNGAPI
+
+// If the user did not make a choice, then select CryptoNG if
+// targeting Windows 8 or above.
+#if !defined(USE_MS_CRYPTOAPI) && !defined(USE_MS_CNGAPI)
+# if !defined(_USING_V110_SDK71_) && ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || \
+     (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
+#  define USE_MS_CNGAPI
+# else
+#  define USE_MS_CRYPTOAPI
+# endif
+#endif
+
+// Begin OS features, like init priorities and random numbers
+#ifndef NO_OS_DEPENDENCE
+
+// CRYPTOPP_INIT_PRIORITY attempts to manage initialization of C++ static objects.
+// Under GCC, the library uses init_priority attribute in the range
+// [CRYPTOPP_INIT_PRIORITY, CRYPTOPP_INIT_PRIORITY+100]. Under Windows,
+// CRYPTOPP_INIT_PRIORITY enlists "#pragma init_seg(lib)". The platforms
+// with gaps are Apple and Sun because they require linker scripts. Apple and
+// Sun will use the library's Singletons to initialize and acquire resources.
+// Also see http://cryptopp.com/wiki/Static_Initialization_Order_Fiasco
+#ifndef CRYPTOPP_INIT_PRIORITY
+# define CRYPTOPP_INIT_PRIORITY 250
+#endif
+
+// CRYPTOPP_USER_PRIORITY is for other libraries and user code that is using Crypto++
+// and managing C++ static object creation. It is guaranteed not to conflict with
+// values used by (or would be used by) the Crypto++ library.
+#ifndef CRYPTOPP_USER_PRIORITY
+# define CRYPTOPP_USER_PRIORITY (CRYPTOPP_INIT_PRIORITY+101)
+#endif
+
+// Most platforms allow us to specify when to create C++ objects. Apple and Sun do not.
+#if (CRYPTOPP_INIT_PRIORITY > 0) && !(defined(NO_OS_DEPENDENCE) || defined(__APPLE__) || defined(__sun__))
+# if (CRYPTOPP_GCC_VERSION >= 30000) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (_INTEL_COMPILER >= 800)
+#  define HAVE_GCC_INIT_PRIORITY 1
+# elif (CRYPTOPP_MSC_VERSION >= 1310)
+#  define HAVE_MSC_INIT_PRIORITY 1
+# elif defined(__xlc__) || defined(__xlC__) || defined(__ibmxl__)
+#  define HAVE_XLC_INIT_PRIORITY 1
+# endif
+#endif  // CRYPTOPP_INIT_PRIORITY, NO_OS_DEPENDENCE, Apple, Sun
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
+#	define HIGHRES_TIMER_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+# if !defined(WINAPI_FAMILY)
+#	define THREAD_TIMER_AVAILABLE
+# elif defined(WINAPI_FAMILY)
+#   if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
+#	  define THREAD_TIMER_AVAILABLE
+#  endif
+# endif
+#endif
+
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+#	define NONBLOCKING_RNG_AVAILABLE
+#	define BLOCKING_RNG_AVAILABLE
+#	define OS_RNG_AVAILABLE
+#endif
+
+// Cygwin/Newlib requires _XOPEN_SOURCE=600
+#if defined(CRYPTOPP_UNIX_AVAILABLE)
+# define UNIX_SIGNALS_AVAILABLE 1
+#endif
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+# if !defined(WINAPI_FAMILY)
+#	define NONBLOCKING_RNG_AVAILABLE
+#	define OS_RNG_AVAILABLE
+# elif defined(WINAPI_FAMILY)
+#   if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
+#	  define NONBLOCKING_RNG_AVAILABLE
+#	  define OS_RNG_AVAILABLE
+#   elif !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
+#     if ((WINVER >= 0x0A00 /*_WIN32_WINNT_WIN10*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/))
+#	    define NONBLOCKING_RNG_AVAILABLE
+#	    define OS_RNG_AVAILABLE
+#     endif
+#   endif
+# endif
+#endif
+
+#endif	// NO_OS_DEPENDENCE
+
+#endif  // CRYPTOPP_CONFIG_OS_H

+ 96 - 0
include/cryptlib/config_ver.h

@@ -0,0 +1,96 @@
+// config_ver.h - written and placed in public domain by Jeffrey Walton
+//                the bits that make up this source file are from the
+//                library's monolithic config.h.
+
+/// \file config_ver.h
+/// \brief Library configuration file
+/// \details <tt>config_ver.h</tt> provides defines for library and compiler
+///  versions.
+/// \details <tt>config.h</tt> was split into components in May 2019 to better
+///  integrate with Autoconf and its feature tests. The splitting occurred so
+///  users could continue to include <tt>config.h</tt> while allowing Autoconf
+///  to write new <tt>config_asm.h</tt> and new <tt>config_cxx.h</tt> using
+///  its feature tests.
+/// \note You should include <tt>config.h</tt> rather than <tt>config_ver.h</tt>
+///  directly.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/835">Issue 835,
+///  Make config.h more autoconf friendly</A>,
+///  <A HREF="https://www.cryptopp.com/wiki/Configure.sh">Configure.sh script</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 8.3
+
+#ifndef CRYPTOPP_CONFIG_VERSION_H
+#define CRYPTOPP_CONFIG_VERSION_H
+
+/// \brief Library major version
+/// \details CRYPTOPP_MAJOR reflects the major version of the library the
+///  headers came from. It is not necessarily the version of the library built
+///  as a shared object if versions are inadvertently mixed and matched.
+/// \sa CRYPTOPP_VERSION, LibraryVersion(), HeaderVersion()
+/// \since Crypto++ 8.2
+#define CRYPTOPP_MAJOR 8
+/// \brief Library minor version
+/// \details CRYPTOPP_MINOR reflects the minor version of the library the
+///  headers came from. It is not necessarily the version of the library built
+///  as a shared object if versions are inadvertently mixed and matched.
+/// \sa CRYPTOPP_VERSION, LibraryVersion(), HeaderVersion()
+/// \since Crypto++ 8.2
+#define CRYPTOPP_MINOR 9
+/// \brief Library revision number
+/// \details CRYPTOPP_REVISION reflects the revision number of the library the
+///  headers came from. It is not necessarily the revision of the library built
+///  as a shared object if versions are inadvertently mixed and matched.
+/// \sa CRYPTOPP_VERSION, LibraryVersion(), HeaderVersion()
+/// \since Crypto++ 8.2
+#define CRYPTOPP_REVISION 0
+
+/// \brief Full library version
+/// \details CRYPTOPP_VERSION reflects the version of the library the headers
+///  came from. It is not necessarily the version of the library built as a
+///  shared object if versions are inadvertently mixed and matched.
+/// \sa CRYPTOPP_MAJOR, CRYPTOPP_MINOR, CRYPTOPP_REVISION, LibraryVersion(), HeaderVersion()
+/// \since Crypto++ 5.6
+#define CRYPTOPP_VERSION 890
+
+// Compiler version macros
+
+// Apple and LLVM Clang versions. Apple Clang version 7.0 roughly equals
+// LLVM Clang version 3.7. Also see https://gist.github.com/yamaya/2924292
+#if defined(__clang__) && defined(__apple_build_version__)
+# define CRYPTOPP_APPLE_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+#elif defined(__clang__)
+# define CRYPTOPP_LLVM_CLANG_VERSION  (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+#endif
+
+// Clang pretends to be other compilers. The compiler gets into
+// code paths that it cannot compile. Unset Clang to save the grief.
+// Also see http://github.com/weidai11/cryptopp/issues/147.
+
+#if defined(__GNUC__) && !defined(__clang__)
+# undef CRYPTOPP_APPLE_CLANG_VERSION
+# undef CRYPTOPP_LLVM_CLANG_VERSION
+# define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(__xlc__) || defined(__xlC__) && !defined(__clang__)
+# undef CRYPTOPP_LLVM_CLANG_VERSION
+# define CRYPTOPP_XLC_VERSION ((__xlC__ / 256) * 10000 + (__xlC__ % 256) * 100)
+#endif
+
+#if defined(__INTEL_COMPILER) && !defined(__clang__)
+# undef CRYPTOPP_LLVM_CLANG_VERSION
+# define CRYPTOPP_INTEL_VERSION (__INTEL_COMPILER)
+#endif
+
+#if defined(_MSC_VER) && !defined(__clang__)
+# undef CRYPTOPP_LLVM_CLANG_VERSION
+# define CRYPTOPP_MSC_VERSION (_MSC_VER)
+#endif
+
+// To control <x86intrin.h> include. May need a guard, like GCC 4.5 and above
+// Also see https://stackoverflow.com/a/42493893 and https://github.com/weidai11/cryptopp/issues/1198
+#if defined(CRYPTOPP_GCC_VERSION) || defined(CRYPTOPP_APPLE_CLANG_VERSION) || defined(CRYPTOPP_LLVM_CLANG_VERSION)
+# define CRYPTOPP_GCC_COMPATIBLE 1
+#endif
+
+#endif  // CRYPTOPP_CONFIG_VERSION_H

File diff suppressed because it is too large
+ 479 - 168
include/cryptlib/cpu.h


+ 25 - 9
include/cryptlib/crc.h

@@ -12,7 +12,7 @@ NAMESPACE_BEGIN(CryptoPP)
 
 const word32 CRC32_NEGL = 0xffffffffL;
 
-#ifdef CRYPTOPP_LITTLE_ENDIAN
+#if (CRYPTOPP_LITTLE_ENDIAN)
 #define CRC32_INDEX(c) (c & 0xff)
 #define CRC32_SHIFTED(c) (c >> 8)
 #else
@@ -25,16 +25,24 @@ const word32 CRC32_NEGL = 0xffffffffL;
 class CRC32 : public HashTransformation
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 4);
 	CRC32();
 	void Update(const byte *input, size_t length);
 	void TruncatedFinal(byte *hash, size_t size);
 	unsigned int DigestSize() const {return DIGESTSIZE;}
-    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "CRC32";}
-    std::string AlgorithmName() const {return StaticAlgorithmName();}
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "CRC32";}
+	std::string AlgorithmName() const {return StaticAlgorithmName();}
 
+	/// \brief Updates a CRC with additional input
+	/// \param b the additional input as a byte
 	void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
-	byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
+
+	/// \brief Retrieves the i-th byte of the CRC
+	/// \param i the additional input as a byte
+	/// \return the byte at the i-th position
+	byte GetCrcByte(size_t i) const {return reinterpret_cast<const byte *>(&m_crc)[i];}
+
+	std::string AlgorithmProvider() const;
 
 protected:
 	void Reset() {m_crc = CRC32_NEGL;}
@@ -50,16 +58,24 @@ private:
 class CRC32C : public HashTransformation
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 4);
 	CRC32C();
 	void Update(const byte *input, size_t length);
 	void TruncatedFinal(byte *hash, size_t size);
 	unsigned int DigestSize() const {return DIGESTSIZE;}
-    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "CRC32C";}
-    std::string AlgorithmName() const {return StaticAlgorithmName();}
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "CRC32C";}
+	std::string AlgorithmName() const {return StaticAlgorithmName();}
 
+	/// \brief Updates a CRC with additional input
+	/// \param b the additional input as a byte
 	void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
-	byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
+
+	/// \brief Retrieves the i-th byte of the CRC
+	/// \param i the additional input as a byte
+	/// \return the byte at the i-th position
+	byte GetCrcByte(size_t i) const {return reinterpret_cast<const byte *>(&m_crc)[i];}
+
+	std::string AlgorithmProvider() const;
 
 protected:
 	void Reset() {m_crc = CRC32_NEGL;}

File diff suppressed because it is too large
+ 276 - 222
include/cryptlib/cryptlib.h


+ 95 - 0
include/cryptlib/darn.h

@@ -0,0 +1,95 @@
+// darn.h - written and placed in public domain by Jeffrey Walton
+//          DARN requires POWER9/ISA 3.0.
+
+// At the moment only GCC 7.0 (and above) seems to support __builtin_darn()
+// and __builtin_darn_32(). However, GCC generates incorrect code. Clang 7.0
+// does not provide them, but it does support assembly instructions. XLC is
+// unknown, but there are no hits when searching IBM's site. To cover more
+// platforms we provide GCC inline assembly like we do with RDRAND and RDSEED.
+// Platforms that don't support GCC inline assembly or the builtin will fail
+// to compile. Also see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91481 and
+// https://gcc.gnu.org/onlinedocs/gcc/Basic-PowerPC-Built-in-Functions-Available-on-ISA-3_002e0.html
+
+/// \file darn.h
+/// \brief Classes for DARN RNG
+/// \sa <A HREF="https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0">Power
+///   ISA Version 3.0B</A>
+/// \since Crypto++ 8.0
+
+#ifndef CRYPTOPP_DARN_H
+#define CRYPTOPP_DARN_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief Exception thrown when a DARN generator encounters
+///    a generator related error.
+/// \since Crypto++ 8.0
+class DARN_Err : public Exception
+{
+public:
+    DARN_Err(const std::string &operation)
+        : Exception(OTHER_ERROR, "DARN: " + operation + " operation failed") {}
+};
+
+/// \brief Hardware generated random numbers using DARN instruction
+/// \details DARN() provides access to Power9's random number generator. The
+///   Crypto++ implementation provides conditioned random numbers from the
+///   generator as opposed to raw random numbers. According to Power ISA 3.0B
+///   manual, a conditioned random number has been processed by hardware to
+///   reduce bias. A raw random number is unconditioned noise source output.
+/// \details According to Power ISA 3.0B manual, the random number generator
+///   provided by the <tt>darn</tt> instruction is NIST SP800-90B and SP800-90C
+///   compliant to the extent possible given the completeness of the standards
+///   at the time the hardware is designed. The random number generator provides
+///   a minimum of 0.5 bits of entropy per bit.
+/// \par Wraps
+///   darn instruction
+/// \sa <A HREF="https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0">Power
+///   ISA Version 3.0B</A>, MaurerRandomnessTest() for random bit generators
+/// \since Crypto++ 8.0
+class DARN : public RandomNumberGenerator
+{
+public:
+    CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "DARN"; }
+
+    virtual ~DARN() {}
+
+    /// \brief Construct a DARN generator
+     /// \throw DARN_Err if the random number generator is not available
+    DARN();
+
+    /// \brief Generate random array of bytes
+    /// \param output the byte buffer
+    /// \param size the length of the buffer, in bytes
+    virtual void GenerateBlock(byte *output, size_t size);
+
+    /// \brief Generate and discard n bytes
+    /// \param n the number of bytes to generate and discard
+    /// \details the RDSEED generator discards words, not bytes. If n is
+    ///   not a multiple of a machine word, then it is rounded up to
+    ///   that size.
+    virtual void DiscardBytes(size_t n);
+
+    /// \brief Update RNG state with additional unpredictable values
+    /// \param input unused
+    /// \param length unused
+    /// \details The operation is a nop for this generator.
+    virtual void IncorporateEntropy(const byte *input, size_t length)
+    {
+        // Override to avoid the base class' throw.
+        CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
+    }
+
+    std::string AlgorithmProvider() const {
+        return "Power9";
+    }
+
+private:
+    SecBlock<byte, AllocatorWithCleanup<byte, true> > m_temp;
+};
+
+NAMESPACE_END
+
+#endif // CRYPTOPP_DARN_H

+ 33 - 33
include/cryptlib/default.h

@@ -56,11 +56,11 @@ class MACBadErr : public DataDecryptorErr
 template <unsigned int BlockSize, unsigned int KeyLength, unsigned int DigestSize, unsigned int SaltSize, unsigned int Iterations>
 struct DataParametersInfo
 {
-	CRYPTOPP_CONSTANT(BLOCKSIZE  = BlockSize)
-	CRYPTOPP_CONSTANT(KEYLENGTH  = KeyLength)
-	CRYPTOPP_CONSTANT(SALTLENGTH = SaltSize)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = DigestSize)
-	CRYPTOPP_CONSTANT(ITERATIONS = Iterations)
+	CRYPTOPP_CONSTANT(BLOCKSIZE  = BlockSize);
+	CRYPTOPP_CONSTANT(KEYLENGTH  = KeyLength);
+	CRYPTOPP_CONSTANT(SALTLENGTH = SaltSize);
+	CRYPTOPP_CONSTANT(DIGESTSIZE = DigestSize);
+	CRYPTOPP_CONSTANT(ITERATIONS = Iterations);
 };
 
 typedef DataParametersInfo<LegacyBlockCipher::BLOCKSIZE, LegacyBlockCipher::DEFAULT_KEYLENGTH, LegacyHashModule::DIGESTSIZE, 8, 200> LegacyParametersInfo;
@@ -78,11 +78,11 @@ template <class BC, class H, class Info>
 class DataEncryptor : public ProxyFilter, public Info
 {
 public:
-	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE)
-	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH)
-	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS)
+	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE);
+	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH);
+	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH);
+	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE);
+	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS);
 
 	/// \brief Construct a DataEncryptor
 	/// \param passphrase a C-String password
@@ -116,23 +116,23 @@ template <class BC, class H, class Info>
 class DataDecryptor : public ProxyFilter, public Info
 {
 public:
-	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE)
-	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH)
-	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS)
+	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE);
+	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH);
+	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH);
+	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE);
+	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS);
 
 	/// \brief Constructs a DataDecryptor
 	/// \param passphrase a C-String password
 	/// \param attachment a BufferedTransformation to attach to this object
-	/// \param throwException a flag specifiying whether an Exception should be thrown on error
+	/// \param throwException a flag specifying whether an Exception should be thrown on error
 	DataDecryptor(const char *passphrase, BufferedTransformation *attachment = NULLPTR, bool throwException=true);
 
 	/// \brief Constructs a DataDecryptor
 	/// \param passphrase a byte string password
 	/// \param passphraseLength the length of the byte string password
 	/// \param attachment a BufferedTransformation to attach to this object
-	/// \param throwException a flag specifiying whether an Exception should be thrown on error
+	/// \param throwException a flag specifying whether an Exception should be thrown on error
 	DataDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULLPTR, bool throwException=true);
 
 	enum State {WAITING_FOR_KEYCHECK, KEY_GOOD, KEY_BAD};
@@ -173,11 +173,11 @@ template <class BC, class H, class MAC, class Info>
 class DataEncryptorWithMAC : public ProxyFilter
 {
 public:
-	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE)
-	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH)
-	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS)
+	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE);
+	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH);
+	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH);
+	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE);
+	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS);
 
 	/// \brief Constructs a DataEncryptorWithMAC
 	/// \param passphrase a C-String password
@@ -218,23 +218,23 @@ template <class BC, class H, class MAC, class Info>
 class DataDecryptorWithMAC : public ProxyFilter
 {
 public:
-	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE)
-	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH)
-	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH)
-	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS)
+	CRYPTOPP_CONSTANT(BLOCKSIZE  = Info::BLOCKSIZE);
+	CRYPTOPP_CONSTANT(KEYLENGTH  = Info::KEYLENGTH);
+	CRYPTOPP_CONSTANT(SALTLENGTH = Info::SALTLENGTH);
+	CRYPTOPP_CONSTANT(DIGESTSIZE = Info::DIGESTSIZE);
+	CRYPTOPP_CONSTANT(ITERATIONS = Info::ITERATIONS);
 
 	/// \brief Constructs a DataDecryptor
 	/// \param passphrase a C-String password
 	/// \param attachment a BufferedTransformation to attach to this object
-	/// \param throwException a flag specifiying whether an Exception should be thrown on error
+	/// \param throwException a flag specifying whether an Exception should be thrown on error
 	DataDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULLPTR, bool throwException=true);
 
 	/// \brief Constructs a DataDecryptor
 	/// \param passphrase a byte string password
 	/// \param passphraseLength the length of the byte string password
 	/// \param attachment a BufferedTransformation to attach to this object
-	/// \param throwException a flag specifiying whether an Exception should be thrown on error
+	/// \param throwException a flag specifying whether an Exception should be thrown on error
 	DataDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULLPTR, bool throwException=true);
 
 	typename DataDecryptor<BC,H,Info>::State CurrentState() const;
@@ -275,12 +275,12 @@ struct DefaultDecryptor : public DataDecryptor<DefaultBlockCipher,DefaultHashMod
 /// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1.
 ///   Crypto++ 5.7 switched to AES and SHA256. The updated algorithms are available with the
 ///   <tt>Default*</tt> classes, and the old algorithms are available with the <tt>Legacy*</tt> classes.
-struct LegacyEncryptorWithMAC : public DataEncryptorWithMAC<LegacyBlockCipher,LegacyHashModule,DefaultMAC,LegacyParametersInfo> {};
+struct LegacyEncryptorWithMAC : public DataEncryptorWithMAC<LegacyBlockCipher,LegacyHashModule,LegacyMAC,LegacyParametersInfo> {};
 /// \brief Password-based decryptor with MAC (deprecated)
 /// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1.
 ///   Crypto++ 5.7 switched to AES and SHA256. The updated algorithms are available with the
 ///   <tt>Default*</tt> classes, and the old algorithms are available with the <tt>Legacy*</tt> classes.
-struct LegacyDecryptorWithMAC : public DataDecryptorWithMAC<LegacyBlockCipher,LegacyHashModule,DefaultMAC,LegacyParametersInfo> {};
+struct LegacyDecryptorWithMAC : public DataDecryptorWithMAC<LegacyBlockCipher,LegacyHashModule,LegacyMAC,LegacyParametersInfo> {};
 /// \brief Password-based encryptor with MAC
 /// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1.
 ///   Crypto++ 5.7 switched to AES and SHA256. The updated algorithms are available with the
@@ -298,8 +298,8 @@ typedef DataDecryptor<LegacyBlockCipher,LegacyHashModule,LegacyParametersInfo> L
 typedef DataEncryptor<DefaultBlockCipher,DefaultHashModule,DefaultParametersInfo> DefaultEncryptor;
 typedef DataDecryptor<DefaultBlockCipher,DefaultHashModule,DefaultParametersInfo> DefaultDecryptor;
 
-typedef DataEncryptorWithMAC<LegacyBlockCipher,LegacyHashModule,DefaultMAC,LegacyParametersInfo> LegacyEncryptorWithMAC;
-typedef DataDecryptorWithMAC<LegacyBlockCipher,LegacyHashModule,DefaultMAC,LegacyParametersInfo> LegacyDecryptorWithMAC;
+typedef DataEncryptorWithMAC<LegacyBlockCipher,LegacyHashModule,LegacyMAC,LegacyParametersInfo> LegacyEncryptorWithMAC;
+typedef DataDecryptorWithMAC<LegacyBlockCipher,LegacyHashModule,LegacyMAC,LegacyParametersInfo> LegacyDecryptorWithMAC;
 
 typedef DataEncryptorWithMAC<DefaultBlockCipher,DefaultHashModule,DefaultMAC,DefaultParametersInfo> DefaultEncryptorWithMAC;
 typedef DataDecryptorWithMAC<DefaultBlockCipher,DefaultHashModule,DefaultMAC,DefaultParametersInfo> DefaultDecryptorWithMAC;

+ 0 - 1
include/cryptlib/dll.h

@@ -40,7 +40,6 @@
 #include "rw.h"
 #include "sha.h"
 #include "skipjack.h"
-#include "trdlocal.h"
 
 #ifdef CRYPTOPP_IMPORTS
 

+ 11 - 3
include/cryptlib/dmac.h

@@ -17,7 +17,7 @@ template <class T>
 class CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs<T>, public MessageAuthenticationCode
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
+	CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE);
 	static std::string StaticAlgorithmName() {return std::string("DMAC(") + T::StaticAlgorithmName() + ")";}
 
 	virtual~DMAC_Base() {}
@@ -28,6 +28,8 @@ public:
 	void TruncatedFinal(byte *mac, size_t size);
 	unsigned int DigestSize() const {return DIGESTSIZE;}
 
+	std::string AlgorithmProvider() const;
+
 private:
 	byte *GenerateSubKeys(const byte *key, size_t keylength);
 
@@ -38,6 +40,12 @@ private:
 	unsigned int m_counter;
 };
 
+template <class T>
+std::string DMAC_Base<T>::AlgorithmProvider() const
+{
+	return m_f2.AlgorithmProvider();
+}
+
 /// \brief DMAC message authentication code
 /// \tparam T class derived from BlockCipherDocumentation
 /// \sa <A HREF="https://eprint.iacr.org/1997/010">CBC MAC for Real-Time Data Sources (08.15.1997)</A>
@@ -82,7 +90,7 @@ void DMAC_Base<T>::TruncatedFinal(byte *mac, size_t size)
 
 	byte pad[T::BLOCKSIZE];
 	byte padByte = byte(T::BLOCKSIZE-m_counter);
-	memset(pad, padByte, padByte);
+	std::memset(pad, padByte, padByte);
 	m_mac1.Update(pad, padByte);
 	m_mac1.TruncatedFinal(mac, size);
 	m_f2.ProcessBlock(mac);
@@ -94,7 +102,7 @@ template <class T>
 byte *DMAC_Base<T>::GenerateSubKeys(const byte *key, size_t keylength)
 {
 	typename T::Encryption cipher(key, keylength);
-	memset(m_subkeys, 0, m_subkeys.size());
+	std::memset(m_subkeys, 0, m_subkeys.size());
 	cipher.ProcessBlock(m_subkeys);
 	m_subkeys[m_subkeys.size()/2 + T::BLOCKSIZE - 1] = 1;
 	cipher.ProcessBlock(m_subkeys+m_subkeys.size()/2);

+ 179 - 0
include/cryptlib/donna.h

@@ -0,0 +1,179 @@
+// donna.h - written and placed in public domain by Jeffrey Walton
+//           Crypto++ specific implementation wrapped around Andrew
+//           Moon's public domain curve25519-donna and ed25519-donna,
+//           https://github.com/floodyberry/curve25519-donna and
+//           https://github.com/floodyberry/ed25519-donna.
+
+// The curve25519 and ed25519 source files multiplex different repos and
+// architectures using namespaces. The repos are Andrew Moon's
+// curve25519-donna and ed25519-donna. The architectures are 32-bit, 64-bit
+// and SSE. For example, 32-bit x25519 uses symbols from Donna::X25519 and
+// Donna::Arch32.
+
+// If needed, see Moon's commit "Go back to ignoring 256th bit [sic]",
+// https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658
+
+/// \file donna.h
+/// \details Functions for curve25519 and ed25519 operations
+/// \details This header provides the entry points into Andrew Moon's
+///   curve25519 and ed25519 curve functions. The Crypto++ classes x25519
+///   and ed25519 use the functions. The functions are in the <tt>Donna</tt>
+///   namespace and are curve25519_mult(), ed25519_publickey(),
+///   ed25519_sign() and ed25519_sign_open().
+/// \details At the moment the hash function for signing is fixed at
+///   SHA512.
+
+#ifndef CRYPTOPP_DONNA_H
+#define CRYPTOPP_DONNA_H
+
+#include "config.h"
+#include "cryptlib.h"
+#include "stdcpp.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+NAMESPACE_BEGIN(Donna)
+
+//***************************** curve25519 *****************************//
+
+/// \brief Generate a public key
+/// \param publicKey byte array for the public key
+/// \param secretKey byte array with the private key
+/// \return 0 on success, non-0 otherwise
+/// \details curve25519_mult() generates a public key from an existing
+///   secret key. Internally curve25519_mult() performs a scalar
+///   multiplication using the base point and writes the result to
+///   <tt>pubkey</tt>.
+int curve25519_mult(byte publicKey[32], const byte secretKey[32]);
+
+/// \brief Generate a shared key
+/// \param sharedKey byte array for the shared secret
+/// \param secretKey byte array with the private key
+/// \param othersKey byte array with the peer's public key
+/// \return 0 on success, non-0 otherwise
+/// \details curve25519_mult() generates a shared key from an existing
+///   secret key and the other party's public key. Internally
+///   curve25519_mult() performs a scalar multiplication using the two keys
+///   and writes the result to <tt>sharedKey</tt>.
+int curve25519_mult(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]);
+
+//******************************* ed25519 *******************************//
+
+/// \brief Creates a public key from a secret key
+/// \param publicKey byte array for the public key
+/// \param secretKey byte array with the private key
+/// \return 0 on success, non-0 otherwise
+/// \details ed25519_publickey() generates a public key from a secret key.
+///   Internally ed25519_publickey() performs a scalar multiplication
+///   using the secret key and then writes the result to <tt>publicKey</tt>.
+int ed25519_publickey(byte publicKey[32], const byte secretKey[32]);
+
+/// \brief Creates a signature on a message
+/// \param message byte array with the message
+/// \param messageLength size of the message, in bytes
+/// \param publicKey byte array with the public key
+/// \param secretKey byte array with the private key
+/// \param signature byte array for the signature
+/// \return 0 on success, non-0 otherwise
+/// \details ed25519_sign() generates a signature on a message using
+///   the public and private keys. The various buffers can be exact
+///   sizes, and do not require extra space like when using the
+///   NaCl library functions.
+/// \details At the moment the hash function for signing is fixed at
+///   SHA512.
+int ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], const byte publicKey[32], byte signature[64]);
+
+/// \brief Creates a signature on a message
+/// \param stream std::istream derived class
+/// \param publicKey byte array with the public key
+/// \param secretKey byte array with the private key
+/// \param signature byte array for the signature
+/// \return 0 on success, non-0 otherwise
+/// \details ed25519_sign() generates a signature on a message using
+///   the public and private keys. The various buffers can be exact
+///   sizes, and do not require extra space like when using the
+///   NaCl library functions.
+/// \details This ed25519_sign() overload handles large streams. It
+///   was added for signing and verifying files that are too large
+///   for a memory allocation.
+/// \details At the moment the hash function for signing is fixed at
+///   SHA512.
+int ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32], byte signature[64]);
+
+/// \brief Verifies a signature on a message
+/// \param message byte array with the message
+/// \param messageLength size of the message, in bytes
+/// \param publicKey byte array with the public key
+/// \param signature byte array with the signature
+/// \return 0 on success, non-0 otherwise
+/// \details ed25519_sign_open() verifies a signature on a message using
+///   the public key. The various buffers can be exact sizes, and do not
+///   require extra space like when using the NaCl library functions.
+/// \details At the moment the hash function for signing is fixed at
+///   SHA512.
+int
+ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]);
+
+/// \brief Verifies a signature on a message
+/// \param stream std::istream derived class
+/// \param publicKey byte array with the public key
+/// \param signature byte array with the signature
+/// \return 0 on success, non-0 otherwise
+/// \details ed25519_sign_open() verifies a signature on a message using
+///   the public key. The various buffers can be exact sizes, and do not
+///   require extra space like when using the NaCl library functions.
+/// \details This ed25519_sign_open() overload handles large streams. It
+///   was added for signing and verifying files that are too large
+///   for a memory allocation.
+/// \details At the moment the hash function for signing is fixed at
+///   SHA512.
+int
+ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64]);
+
+//****************************** Internal ******************************//
+
+#ifndef CRYPTOPP_DOXYGEN_PROCESSING
+
+// CRYPTOPP_WORD128_AVAILABLE mostly depends upon GCC support for
+// __SIZEOF_INT128__. If __SIZEOF_INT128__ is not available then Moon
+// provides routines for MSC and GCC. It should cover most platforms,
+// but there are gaps like MS ARM64 and XLC. We tried to enable the
+// 64-bit path for SunCC from 12.5 but we got the dreaded compile
+// error "The operand ___LCM cannot be assigned to".
+
+#if defined(CRYPTOPP_WORD128_AVAILABLE) || \
+   (defined(CRYPTOPP_MSC_VERSION) && defined(_M_X64))
+# define CRYPTOPP_CURVE25519_64BIT 1
+#else
+# define CRYPTOPP_CURVE25519_32BIT 1
+#endif
+
+// Benchmarking on a modern 64-bit Core i5-6400 @2.7 GHz shows SSE2 on Linux
+// is not profitable. Here are the numbers in milliseconds/operation:
+//
+//   * Langley, C++, 0.050
+//   * Moon, C++: 0.040
+//   * Moon, SSE2: 0.061
+//   * Moon, native: 0.045
+//
+// However, a modern 64-bit Core i5-3200 @2.5 GHz shows SSE2 is profitable
+// for MS compilers. Here are the numbers in milliseconds/operation:
+//
+//   * x86, no SSE2, 0.294
+//   * x86, SSE2, 0.097
+//   * x64, no SSE2, 0.081
+//   * x64, SSE2, 0.071
+
+#if defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
+# define CRYPTOPP_CURVE25519_SSE2 1
+#endif
+
+#if (CRYPTOPP_CURVE25519_SSE2)
+  extern int curve25519_mult_SSE2(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]);
+#endif
+
+#endif  // CRYPTOPP_DOXYGEN_PROCESSING
+
+NAMESPACE_END  // Donna
+NAMESPACE_END  // CryptoPP
+
+#endif  // CRYPTOPP_DONNA_H

+ 411 - 0
include/cryptlib/donna_32.h

@@ -0,0 +1,411 @@
+// donna_32.h - written and placed in public domain by Jeffrey Walton
+//              Crypto++ specific implementation wrapped around Andrew
+//              Moon's public domain curve25519-donna and ed25519-donna,
+//              https://github.com/floodyberry/curve25519-donna and
+//              https://github.com/floodyberry/ed25519-donna.
+
+// This source file multiplexes two different repos using namespaces. This
+// was a little easier from a project management standpoint. We only need
+// two files per architecture at the expense of namespaces and bloat.
+
+#ifndef CRYPTOPP_DONNA_32_H
+#define CRYPTOPP_DONNA_32_H
+#ifndef CRYPTOPP_DOXYGEN_PROCESSING
+
+#include "config.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+NAMESPACE_BEGIN(Donna)
+NAMESPACE_BEGIN(Arch32)
+
+using CryptoPP::byte;
+using CryptoPP::word32;
+using CryptoPP::word64;
+
+// ******************** x25519 Agreement ************************* //
+
+#define ALIGN(n) CRYPTOPP_ALIGN_DATA(n)
+#define mul32x32_64(a,b) (((word64)(a))*(b))
+
+typedef word32 bignum25519[10];
+
+const byte basePoint[32] = {9};
+const word32 reduce_mask_25 = (1 << 25) - 1;
+const word32 reduce_mask_26 = (1 << 26) - 1;
+
+// ****************** ed25519 Signatures *********************** //
+
+typedef byte hash_512bits[64];
+
+const int bignum256modm_bits_per_limb = 30;
+const int bignum256modm_limb_size = 9;
+typedef word32 bignum256modm_element_t;
+typedef bignum256modm_element_t bignum256modm[9];
+
+struct ge25519 {
+    bignum25519 x, y, z, t;
+};
+
+struct ge25519_p1p1 {
+    bignum25519 x, y, z, t;
+};
+
+struct ge25519_niels {
+    bignum25519 ysubx, xaddy, t2d;
+};
+
+struct ge25519_pniels {
+    bignum25519 ysubx, xaddy, z, t2d;
+};
+
+#define S1_SWINDOWSIZE 5
+#define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2))
+#define S2_SWINDOWSIZE 7
+#define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2))
+
+// *************** ed25519-donna-32bit-tables.h *************** //
+
+ALIGN(16) const ge25519 ge25519_basepoint = {
+    {0x0325d51a,0x018b5823,0x00f6592a,0x0104a92d,0x01a4b31d,0x01d6dc5c,0x027118fe,0x007fd814,0x013cd6e5,0x0085a4db},
+    {0x02666658,0x01999999,0x00cccccc,0x01333333,0x01999999,0x00666666,0x03333333,0x00cccccc,0x02666666,0x01999999},
+    {0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000},
+    {0x01b7dda3,0x01a2ace9,0x025eadbb,0x0003ba8a,0x0083c27e,0x00abe37d,0x01274732,0x00ccacdd,0x00fd78b7,0x019e1d7c}
+};
+
+ALIGN(16) const bignum25519 ge25519_ecd = {
+    0x035978a3,0x00d37284,0x03156ebd,0x006a0a0e,0x0001c029,0x0179e898,0x03a03cbb,0x01ce7198,0x02e2b6ff,0x01480db3
+};
+
+ALIGN(16) const bignum25519 ge25519_ec2d = {
+    0x02b2f159,0x01a6e509,0x022add7a,0x00d4141d,0x00038052,0x00f3d130,0x03407977,0x019ce331,0x01c56dff,0x00901b67
+};
+
+ALIGN(16) const bignum25519 ge25519_sqrtneg1 = {
+    0x020ea0b0,0x0186c9d2,0x008f189d,0x0035697f,0x00bd0c60,0x01fbd7a7,0x02804c9e,0x01e16569,0x0004fc1d,0x00ae0c92
+};
+
+ALIGN(16) const ge25519_niels ge25519_niels_sliding_multiples[32] = {
+    {{0x0340913e,0x000e4175,0x03d673a2,0x002e8a05,0x03f4e67c,0x008f8a09,0x00c21a34,0x004cf4b8,0x01298f81,0x0113f4be},{0x018c3b85,0x0124f1bd,0x01c325f7,0x0037dc60,0x033e4cb7,0x003d42c2,0x01a44c32,0x014ca4e1,0x03a33d4b,0x001f3e74},{0x037aaa68,0x00448161,0x0093d579,0x011e6556,0x009b67a0,0x0143598c,0x01bee5ee,0x00b50b43,0x0289f0c6,0x01bc45ed}},
+    {{0x00fcd265,0x0047fa29,0x034faacc,0x01ef2e0d,0x00ef4d4f,0x014bd6bd,0x00f98d10,0x014c5026,0x007555bd,0x00aae456},{0x00ee9730,0x016c2a13,0x017155e4,0x01874432,0x00096a10,0x01016732,0x01a8014f,0x011e9823,0x01b9a80f,0x01e85938},{0x01d0d889,0x01a4cfc3,0x034c4295,0x0110e1ae,0x0162508c,0x00f2db4c,0x0072a2c6,0x0098da2e,0x02f12b9b,0x0168a09a}},
+    {{0x0047d6ba,0x0060b0e9,0x0136eff2,0x008a5939,0x03540053,0x0064a087,0x02788e5c,0x00be7c67,0x033eb1b5,0x005529f9},{0x00a5bb33,0x00af1102,0x01a05442,0x001e3af7,0x02354123,0x00bfec44,0x01f5862d,0x00dd7ba3,0x03146e20,0x00a51733},{0x012a8285,0x00f6fc60,0x023f9797,0x003e85ee,0x009c3820,0x01bda72d,0x01b3858d,0x00d35683,0x0296b3bb,0x010eaaf9}},
+    {{0x023221b1,0x01cb26aa,0x0074f74d,0x0099ddd1,0x01b28085,0x00192c3a,0x013b27c9,0x00fc13bd,0x01d2e531,0x0075bb75},{0x004ea3bf,0x00973425,0x001a4d63,0x01d59cee,0x01d1c0d4,0x00542e49,0x01294114,0x004fce36,0x029283c9,0x01186fa9},{0x01b8b3a2,0x00db7200,0x00935e30,0x003829f5,0x02cc0d7d,0x0077adf3,0x0220dd2c,0x0014ea53,0x01c6a0f9,0x01ea7eec}},
+    {{0x039d8064,0x01885f80,0x00337e6d,0x01b7a902,0x02628206,0x015eb044,0x01e30473,0x0191f2d9,0x011fadc9,0x01270169},{0x02a8632f,0x0199e2a9,0x00d8b365,0x017a8de2,0x02994279,0x0086f5b5,0x0119e4e3,0x01eb39d6,0x0338add7,0x00d2e7b4},{0x0045af1b,0x013a2fe4,0x0245e0d6,0x014538ce,0x038bfe0f,0x01d4cf16,0x037e14c9,0x0160d55e,0x0021b008,0x01cf05c8}},
+    {{0x01864348,0x01d6c092,0x0070262b,0x014bb844,0x00fb5acd,0x008deb95,0x003aaab5,0x00eff474,0x00029d5c,0x0062ad66},{0x02802ade,0x01c02122,0x01c4e5f7,0x00781181,0x039767fb,0x01703406,0x0342388b,0x01f5e227,0x022546d8,0x0109d6ab},{0x016089e9,0x00cb317f,0x00949b05,0x01099417,0x000c7ad2,0x011a8622,0x0088ccda,0x01290886,0x022b53df,0x00f71954}},
+    {{0x027fbf93,0x01c04ecc,0x01ed6a0d,0x004cdbbb,0x02bbf3af,0x00ad5968,0x01591955,0x0094f3a2,0x02d17602,0x00099e20},{0x02007f6d,0x003088a8,0x03db77ee,0x00d5ade6,0x02fe12ce,0x0107ba07,0x0107097d,0x00482a6f,0x02ec346f,0x008d3f5f},{0x032ea378,0x0028465c,0x028e2a6c,0x018efc6e,0x0090df9a,0x01a7e533,0x039bfc48,0x010c745d,0x03daa097,0x0125ee9b}},
+    {{0x028ccf0b,0x00f36191,0x021ac081,0x012154c8,0x034e0a6e,0x01b25192,0x00180403,0x01d7eea1,0x00218d05,0x010ed735},{0x03cfeaa0,0x01b300c4,0x008da499,0x0068c4e1,0x0219230a,0x01f2d4d0,0x02defd60,0x00e565b7,0x017f12de,0x018788a4},{0x03d0b516,0x009d8be6,0x03ddcbb3,0x0071b9fe,0x03ace2bd,0x01d64270,0x032d3ec9,0x01084065,0x0210ae4d,0x01447584}},
+    {{0x0020de87,0x00e19211,0x01b68102,0x00b5ac97,0x022873c0,0x01942d25,0x01271394,0x0102073f,0x02fe2482,0x01c69ff9},{0x010e9d81,0x019dbbe5,0x0089f258,0x006e06b8,0x02951883,0x018f1248,0x019b3237,0x00bc7553,0x024ddb85,0x01b4c964},{0x01c8c854,0x0060ae29,0x01406d8e,0x01cff2f9,0x00cff451,0x01778d0c,0x03ac8c41,0x01552e59,0x036559ee,0x011d1b12}},
+    {{0x00741147,0x0151b219,0x01092690,0x00e877e6,0x01f4d6bb,0x0072a332,0x01cd3b03,0x00dadff2,0x0097db5e,0x0086598d},{0x01c69a2b,0x01decf1b,0x02c2fa6e,0x013b7c4f,0x037beac8,0x013a16b5,0x028e7bda,0x01f6e8ac,0x01e34fe9,0x01726947},{0x01f10e67,0x003c73de,0x022b7ea2,0x010f32c2,0x03ff776a,0x00142277,0x01d38b88,0x00776138,0x03c60822,0x01201140}},
+    {{0x0236d175,0x0008748e,0x03c6476d,0x013f4cdc,0x02eed02a,0x00838a47,0x032e7210,0x018bcbb3,0x00858de4,0x01dc7826},{0x00a37fc7,0x0127b40b,0x01957884,0x011d30ad,0x02816683,0x016e0e23,0x00b76be4,0x012db115,0x02516506,0x0154ce62},{0x00451edf,0x00bd749e,0x03997342,0x01cc2c4c,0x00eb6975,0x01a59508,0x03a516cf,0x00c228ef,0x0168ff5a,0x01697b47}},
+    {{0x00527359,0x01783156,0x03afd75c,0x00ce56dc,0x00e4b970,0x001cabe9,0x029e0f6d,0x0188850c,0x0135fefd,0x00066d80},{0x02150e83,0x01448abf,0x02bb0232,0x012bf259,0x033c8268,0x00711e20,0x03fc148f,0x005e0e70,0x017d8bf9,0x0112b2e2},{0x02134b83,0x001a0517,0x0182c3cc,0x00792182,0x0313d799,0x001a3ed7,0x0344547e,0x01f24a0d,0x03de6ad2,0x00543127}},
+    {{0x00dca868,0x00618f27,0x015a1709,0x00ddc38a,0x0320fd13,0x0036168d,0x0371ab06,0x01783fc7,0x0391e05f,0x01e29b5d},{0x01471138,0x00fca542,0x00ca31cf,0x01ca7bad,0x0175bfbc,0x01a708ad,0x03bce212,0x01244215,0x0075bb99,0x01acad68},{0x03a0b976,0x01dc12d1,0x011aab17,0x00aba0ba,0x029806cd,0x0142f590,0x018fd8ea,0x01a01545,0x03c4ad55,0x01c971ff}},
+    {{0x00d098c0,0x000afdc7,0x006cd230,0x01276af3,0x03f905b2,0x0102994c,0x002eb8a4,0x015cfbeb,0x025f855f,0x01335518},{0x01cf99b2,0x0099c574,0x01a69c88,0x00881510,0x01cd4b54,0x0112109f,0x008abdc5,0x0074647a,0x0277cb1f,0x01e53324},{0x02ac5053,0x01b109b0,0x024b095e,0x016997b3,0x02f26bb6,0x00311021,0x00197885,0x01d0a55a,0x03b6fcc8,0x01c020d5}},
+    {{0x02584a34,0x00e7eee0,0x03257a03,0x011e95a3,0x011ead91,0x00536202,0x00b1ce24,0x008516c6,0x03669d6d,0x004ea4a8},{0x00773f01,0x0019c9ce,0x019f6171,0x01d4afde,0x02e33323,0x01ad29b6,0x02ead1dc,0x01ed51a5,0x01851ad0,0x001bbdfa},{0x00577de5,0x00ddc730,0x038b9952,0x00f281ae,0x01d50390,0x0002e071,0x000780ec,0x010d448d,0x01f8a2af,0x00f0a5b7}},
+    {{0x031f2541,0x00d34bae,0x0323ff9d,0x003a056d,0x02e25443,0x00a1ad05,0x00d1bee8,0x002f7f8e,0x03007477,0x002a24b1},{0x0114a713,0x01457e76,0x032255d5,0x01cc647f,0x02a4bdef,0x0153d730,0x00118bcf,0x00f755ff,0x013490c7,0x01ea674e},{0x02bda3e8,0x00bb490d,0x00f291ea,0x000abf40,0x01dea321,0x002f9ce0,0x00b2b193,0x00fa54b5,0x0128302f,0x00a19d8b}},
+    {{0x022ef5bd,0x01638af3,0x038c6f8a,0x01a33a3d,0x039261b2,0x01bb89b8,0x010bcf9d,0x00cf42a9,0x023d6f17,0x01da1bca},{0x00e35b25,0x000d824f,0x0152e9cf,0x00ed935d,0x020b8460,0x01c7b83f,0x00c969e5,0x01a74198,0x0046a9d9,0x00cbc768},{0x01597c6a,0x0144a99b,0x00a57551,0x0018269c,0x023c464c,0x0009b022,0x00ee39e1,0x0114c7f2,0x038a9ad2,0x01584c17}},
+    {{0x03b0c0d5,0x00b30a39,0x038a6ce4,0x01ded83a,0x01c277a6,0x01010a61,0x0346d3eb,0x018d995e,0x02f2c57c,0x000c286b},{0x0092aed1,0x0125e37b,0x027ca201,0x001a6b6b,0x03290f55,0x0047ba48,0x018d916c,0x01a59062,0x013e35d4,0x0002abb1},{0x003ad2aa,0x007ddcc0,0x00c10f76,0x0001590b,0x002cfca6,0x000ed23e,0x00ee4329,0x00900f04,0x01c24065,0x0082fa70}},
+    {{0x02025e60,0x003912b8,0x0327041c,0x017e5ee5,0x02c0ecec,0x015a0d1c,0x02b1ce7c,0x0062220b,0x0145067e,0x01a5d931},{0x009673a6,0x00e1f609,0x00927c2a,0x016faa37,0x01650ef0,0x016f63b5,0x03cd40e1,0x003bc38f,0x0361f0ac,0x01d42acc},{0x02f81037,0x008ca0e8,0x017e23d1,0x011debfe,0x01bcbb68,0x002e2563,0x03e8add6,0x000816e5,0x03fb7075,0x0153e5ac}},
+    {{0x02b11ecd,0x016bf185,0x008f22ef,0x00e7d2bb,0x0225d92e,0x00ece785,0x00508873,0x017e16f5,0x01fbe85d,0x01e39a0e},{0x01669279,0x017c810a,0x024941f5,0x0023ebeb,0x00eb7688,0x005760f1,0x02ca4146,0x0073cde7,0x0052bb75,0x00f5ffa7},{0x03b8856b,0x00cb7dcd,0x02f14e06,0x001820d0,0x01d74175,0x00e59e22,0x03fba550,0x00484641,0x03350088,0x01c3c9a3}},
+    {{0x00dcf355,0x0104481c,0x0022e464,0x01f73fe7,0x00e03325,0x0152b698,0x02ef769a,0x00973663,0x00039b8c,0x0101395b},{0x01805f47,0x019160ec,0x03832cd0,0x008b06eb,0x03d4d717,0x004cb006,0x03a75b8f,0x013b3d30,0x01cfad88,0x01f034d1},{0x0078338a,0x01c7d2e3,0x02bc2b23,0x018b3f05,0x0280d9aa,0x005f3d44,0x0220a95a,0x00eeeb97,0x0362aaec,0x00835d51}},
+    {{0x01b9f543,0x013fac4d,0x02ad93ae,0x018ef464,0x0212cdf7,0x01138ba9,0x011583ab,0x019c3d26,0x028790b4,0x00e2e2b6},{0x033bb758,0x01f0dbf1,0x03734bd1,0x0129b1e5,0x02b3950e,0x003bc922,0x01a53ec8,0x018c5532,0x006f3cee,0x00ae3c79},{0x0351f95d,0x0012a737,0x03d596b8,0x017658fe,0x00ace54a,0x008b66da,0x0036c599,0x012a63a2,0x032ceba1,0x00126bac}},
+    {{0x03dcfe7e,0x019f4f18,0x01c81aee,0x0044bc2b,0x00827165,0x014f7c13,0x03b430f0,0x00bf96cc,0x020c8d62,0x01471997},{0x01fc7931,0x001f42dd,0x00ba754a,0x005bd339,0x003fbe49,0x016b3930,0x012a159c,0x009f83b0,0x03530f67,0x01e57b85},{0x02ecbd81,0x0096c294,0x01fce4a9,0x017701a5,0x0175047d,0x00ee4a31,0x012686e5,0x008efcd4,0x0349dc54,0x01b3466f}},
+    {{0x02179ca3,0x01d86414,0x03f0afd0,0x00305964,0x015c7428,0x0099711e,0x015d5442,0x00c71014,0x01b40b2e,0x01d483cf},{0x01afc386,0x01984859,0x036203ff,0x0045c6a8,0x0020a8aa,0x00990baa,0x03313f10,0x007ceede,0x027429e4,0x017806ce},{0x039357a1,0x0142f8f4,0x0294a7b6,0x00eaccf4,0x0259edb3,0x01311e6e,0x004d326f,0x0130c346,0x01ccef3c,0x01c424b2}},
+    {{0x0364918c,0x00148fc0,0x01638a7b,0x01a1fd5b,0x028ad013,0x0081e5a4,0x01a54f33,0x0174e101,0x003d0257,0x003a856c},{0x00051dcf,0x00f62b1d,0x0143d0ad,0x0042adbd,0x000fda90,0x01743ceb,0x0173e5e4,0x017bc749,0x03b7137a,0x0105ce96},{0x00f9218a,0x015b8c7c,0x00e102f8,0x0158d7e2,0x0169a5b8,0x00b2f176,0x018b347a,0x014cfef2,0x0214a4e3,0x017f1595}},
+    {{0x006d7ae5,0x0195c371,0x0391e26d,0x0062a7c6,0x003f42ab,0x010dad86,0x024f8198,0x01542b2a,0x0014c454,0x0189c471},{0x0390988e,0x00b8799d,0x02e44912,0x0078e2e6,0x00075654,0x01923eed,0x0040cd72,0x00a37c76,0x0009d466,0x00c8531d},{0x02651770,0x00609d01,0x0286c265,0x0134513c,0x00ee9281,0x005d223c,0x035c760c,0x00679b36,0x0073ecb8,0x016faa50}},
+    {{0x02c89be4,0x016fc244,0x02f38c83,0x018beb72,0x02b3ce2c,0x0097b065,0x034f017b,0x01dd957f,0x00148f61,0x00eab357},{0x0343d2f8,0x003398fc,0x011e368e,0x00782a1f,0x00019eea,0x00117b6f,0x0128d0d1,0x01a5e6bb,0x01944f1b,0x012b41e1},{0x03318301,0x018ecd30,0x0104d0b1,0x0038398b,0x03726701,0x019da88c,0x002d9769,0x00a7a681,0x031d9028,0x00ebfc32}},
+    {{0x0220405e,0x0171face,0x02d930f8,0x017f6d6a,0x023b8c47,0x0129d5f9,0x02972456,0x00a3a524,0x006f4cd2,0x004439fa},{0x00c53505,0x0190c2fd,0x00507244,0x009930f9,0x01a39270,0x01d327c6,0x0399bc47,0x01cfe13d,0x0332bd99,0x00b33e7d},{0x0203f5e4,0x003627b5,0x00018af8,0x01478581,0x004a2218,0x002e3bb7,0x039384d0,0x0146ea62,0x020b9693,0x0017155f}},
+    {{0x03c97e6f,0x00738c47,0x03b5db1f,0x01808fcf,0x01e8fc98,0x01ed25dd,0x01bf5045,0x00eb5c2b,0x0178fe98,0x01b85530},{0x01c20eb0,0x01aeec22,0x030b9eee,0x01b7d07e,0x0187e16f,0x014421fb,0x009fa731,0x0040b6d7,0x00841861,0x00a27fbc},{0x02d69abf,0x0058cdbf,0x0129f9ec,0x013c19ae,0x026c5b93,0x013a7fe7,0x004bb2ba,0x0063226f,0x002a95ca,0x01abefd9}},
+    {{0x02f5d2c1,0x00378318,0x03734fb5,0x01258073,0x0263f0f6,0x01ad70e0,0x01b56d06,0x01188fbd,0x011b9503,0x0036d2e1},{0x0113a8cc,0x01541c3e,0x02ac2bbc,0x01d95867,0x01f47459,0x00ead489,0x00ab5b48,0x01db3b45,0x00edb801,0x004b024f},{0x00b8190f,0x011fe4c2,0x00621f82,0x010508d7,0x001a5a76,0x00c7d7fd,0x03aab96d,0x019cd9dc,0x019c6635,0x00ceaa1e}},
+    {{0x01085cf2,0x01fd47af,0x03e3f5e1,0x004b3e99,0x01e3d46a,0x0060033c,0x015ff0a8,0x0150cdd8,0x029e8e21,0x008cf1bc},{0x00156cb1,0x003d623f,0x01a4f069,0x00d8d053,0x01b68aea,0x01ca5ab6,0x0316ae43,0x0134dc44,0x001c8d58,0x0084b343},{0x0318c781,0x0135441f,0x03a51a5e,0x019293f4,0x0048bb37,0x013d3341,0x0143151e,0x019c74e1,0x00911914,0x0076ddde}},
+    {{0x006bc26f,0x00d48e5f,0x00227bbe,0x00629ea8,0x01ea5f8b,0x0179a330,0x027a1d5f,0x01bf8f8e,0x02d26e2a,0x00c6b65e},{0x01701ab6,0x0051da77,0x01b4b667,0x00a0ce7c,0x038ae37b,0x012ac852,0x03a0b0fe,0x0097c2bb,0x00a017d2,0x01eb8b2a},{0x0120b962,0x0005fb42,0x0353b6fd,0x0061f8ce,0x007a1463,0x01560a64,0x00e0a792,0x01907c92,0x013a6622,0x007b47f1}}
+};
+
+// *************** modm-donna-32bit.h *************** //
+
+const bignum256modm modm_m = {
+    0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8,
+    0x00000014, 0x00000000, 0x00000000, 0x00000000,
+    0x00001000
+};
+
+const bignum256modm modm_mu = {
+    0x0a2c131b, 0x3673968c, 0x06329a7e, 0x01885742,
+    0x3fffeb21, 0x3fffffff, 0x3fffffff, 0x3fffffff,
+    0x000fffff
+};
+
+/* multiples of p */
+const word32 twoP0       = 0x07ffffda;
+const word32 twoP13579   = 0x03fffffe;
+const word32 twoP2468    = 0x07fffffe;
+const word32 fourP0      = 0x0fffffb4;
+const word32 fourP13579  = 0x07fffffc;
+const word32 fourP2468   = 0x0ffffffc;
+
+// *************** ed25519-donna-basepoint-table.h *************** //
+
+/* multiples of the base point in packed {ysubx, xaddy, t2d} form */
+ALIGN(16) const byte ge25519_niels_base_multiples[256][96] = {
+    {0x3e,0x91,0x40,0xd7,0x05,0x39,0x10,0x9d,0xb3,0xbe,0x40,0xd1,0x05,0x9f,0x39,0xfd,0x09,0x8a,0x8f,0x68,0x34,0x84,0xc1,0xa5,0x67,0x12,0xf8,0x98,0x92,0x2f,0xfd,0x44,0x85,0x3b,0x8c,0xf5,0xc6,0x93,0xbc,0x2f,0x19,0x0e,0x8c,0xfb,0xc6,0x2d,0x93,0xcf,0xc2,0x42,0x3d,0x64,0x98,0x48,0x0b,0x27,0x65,0xba,0xd4,0x33,0x3a,0x9d,0xcf,0x07,0x59,0xbb,0x6f,0x4b,0x67,0x15,0xbd,0xdb,0xea,0xa5,0xa2,0xee,0x00,0x3f,0xe1,0x41,0xfa,0xc6,0x57,0xc9,0x1c,0x9d,0xd4,0xcd,0xca,0xec,0x16,0xaf,0x1f,0xbe,0x0e,0x4f},
+    {0xa8,0xd5,0xb4,0x42,0x60,0xa5,0x99,0x8a,0xf6,0xac,0x60,0x4e,0x0c,0x81,0x2b,0x8f,0xaa,0x37,0x6e,0xb1,0x6b,0x23,0x9e,0xe0,0x55,0x25,0xc9,0x69,0xa6,0x95,0xb5,0x6b,0xd7,0x71,0x3c,0x93,0xfc,0xe7,0x24,0x92,0xb5,0xf5,0x0f,0x7a,0x96,0x9d,0x46,0x9f,0x02,0x07,0xd6,0xe1,0x65,0x9a,0xa6,0x5a,0x2e,0x2e,0x7d,0xa8,0x3f,0x06,0x0c,0x59,0x02,0x68,0xd3,0xda,0xaa,0x7e,0x34,0x6e,0x05,0x48,0xee,0x83,0x93,0x59,0xf3,0xba,0x26,0x68,0x07,0xe6,0x10,0xbe,0xca,0x3b,0xb8,0xd1,0x5e,0x16,0x0a,0x4f,0x31,0x49},
+    {0x65,0xd2,0xfc,0xa4,0xe8,0x1f,0x61,0x56,0x7d,0xba,0xc1,0xe5,0xfd,0x53,0xd3,0x3b,0xbd,0xd6,0x4b,0x21,0x1a,0xf3,0x31,0x81,0x62,0xda,0x5b,0x55,0x87,0x15,0xb9,0x2a,0x30,0x97,0xee,0x4c,0xa8,0xb0,0x25,0xaf,0x8a,0x4b,0x86,0xe8,0x30,0x84,0x5a,0x02,0x32,0x67,0x01,0x9f,0x02,0x50,0x1b,0xc1,0xf4,0xf8,0x80,0x9a,0x1b,0x4e,0x16,0x7a,0x34,0x48,0x67,0xf1,0xf4,0x11,0xf2,0x9b,0x95,0xf8,0x2d,0xf6,0x17,0x6b,0x4e,0xb8,0x4e,0x2a,0x72,0x5b,0x07,0x6f,0xde,0xd7,0x21,0x2a,0xbb,0x63,0xb9,0x04,0x9a,0x54},
+    {0xbf,0x18,0x68,0x05,0x0a,0x05,0xfe,0x95,0xa9,0xfa,0x60,0x56,0x71,0x89,0x7e,0x32,0x73,0x50,0xa0,0x06,0xcd,0xe3,0xe8,0xc3,0x9a,0xa4,0x45,0x74,0x4c,0x3f,0x93,0x27,0x9f,0x09,0xfc,0x8e,0xb9,0x51,0x73,0x28,0x38,0x25,0xfd,0x7d,0xf4,0xc6,0x65,0x67,0x65,0x92,0x0a,0xfb,0x3d,0x8d,0x34,0xca,0x27,0x87,0xe5,0x21,0x03,0x91,0x0e,0x68,0xb0,0x26,0x14,0xe5,0xec,0x45,0x1e,0xbf,0x94,0x0f,0xba,0x6d,0x3d,0xc6,0x2b,0xe3,0xc0,0x52,0xf8,0x8c,0xd5,0x74,0x29,0xe4,0x18,0x4c,0xe6,0xb0,0xb1,0x79,0xf0,0x44},
+    {0xba,0xd6,0x47,0xa4,0xc3,0x82,0x91,0x7f,0xb7,0x29,0x27,0x4b,0xd1,0x14,0x00,0xd5,0x87,0xa0,0x64,0xb8,0x1c,0xf1,0x3c,0xe3,0xf3,0x55,0x1b,0xeb,0x73,0x7e,0x4a,0x15,0x33,0xbb,0xa5,0x08,0x44,0xbc,0x12,0xa2,0x02,0xed,0x5e,0xc7,0xc3,0x48,0x50,0x8d,0x44,0xec,0xbf,0x5a,0x0c,0xeb,0x1b,0xdd,0xeb,0x06,0xe2,0x46,0xf1,0xcc,0x45,0x29,0xb3,0x03,0xd0,0xe7,0x79,0xa1,0x32,0xc8,0x7e,0x4d,0x12,0x00,0x0a,0x9d,0x72,0x5f,0xf3,0x8f,0x6d,0x0e,0xa1,0xd4,0xc1,0x62,0x98,0x7a,0xb2,0x38,0x59,0xac,0xb8,0x68},
+    {0xa4,0x8c,0x7d,0x7b,0xb6,0x06,0x98,0x49,0x39,0x27,0xd2,0x27,0x84,0xe2,0x5b,0x57,0xb9,0x53,0x45,0x20,0xe7,0x5c,0x08,0xbb,0x84,0x78,0x41,0xae,0x41,0x4c,0xb6,0x38,0x31,0x71,0x15,0x77,0xeb,0xee,0x0c,0x3a,0x88,0xaf,0xc8,0x00,0x89,0x15,0x27,0x9b,0x36,0xa7,0x59,0xda,0x68,0xb6,0x65,0x80,0xbd,0x38,0xcc,0xa2,0xb6,0x7b,0xe5,0x51,0xa4,0xe3,0x9d,0x68,0x91,0xad,0x9d,0x8f,0x37,0x91,0xfb,0xf8,0x28,0x24,0x5f,0x17,0x88,0xb9,0xcf,0x9f,0x32,0xb5,0x0a,0x05,0x9f,0xc0,0x54,0x13,0xa2,0xdf,0x65,0x78},
+    {0xb1,0x21,0x32,0xaa,0x9a,0x2c,0x6f,0xba,0xa7,0x23,0xba,0x3b,0x53,0x21,0xa0,0x6c,0x3a,0x2c,0x19,0x92,0x4f,0x76,0xea,0x9d,0xe0,0x17,0x53,0x2e,0x5d,0xdd,0x6e,0x1d,0xbf,0xa3,0x4e,0x94,0xd0,0x5c,0x1a,0x6b,0xd2,0xc0,0x9d,0xb3,0x3a,0x35,0x70,0x74,0x49,0x2e,0x54,0x28,0x82,0x52,0xb2,0x71,0x7e,0x92,0x3c,0x28,0x69,0xea,0x1b,0x46,0x36,0xda,0x0f,0xab,0xac,0x8a,0x7a,0x21,0xc8,0x49,0x35,0x3d,0x54,0xc6,0x28,0xa5,0x68,0x75,0xab,0x13,0x8b,0x5b,0xd0,0x37,0x37,0xbc,0x2c,0x3a,0x62,0xef,0x3c,0x23},
+    {0xd9,0x34,0x92,0xf3,0xed,0x5d,0xa7,0xe2,0xf9,0x58,0xb5,0xe1,0x80,0x76,0x3d,0x96,0xfb,0x23,0x3c,0x6e,0xac,0x41,0x27,0x2c,0xc3,0x01,0x0e,0x32,0xa1,0x24,0x90,0x3a,0x8f,0x3e,0xdd,0x04,0x66,0x59,0xb7,0x59,0x2c,0x70,0x88,0xe2,0x77,0x03,0xb3,0x6c,0x23,0xc3,0xd9,0x5e,0x66,0x9c,0x33,0xb1,0x2f,0xe5,0xbc,0x61,0x60,0xe7,0x15,0x09,0x7e,0xa3,0x34,0xa8,0x35,0xe8,0x7d,0xdf,0xea,0x57,0x98,0x68,0xda,0x9c,0xe1,0x8b,0x26,0xb3,0x67,0x71,0x36,0x85,0x11,0x2c,0xc2,0xd5,0xef,0xdb,0xd9,0xb3,0x9e,0x58},
+    {0x5e,0x51,0xaa,0x49,0x54,0x63,0x5b,0xed,0x3a,0x82,0xc6,0x0b,0x9f,0xc4,0x65,0xa8,0xc4,0xd1,0x42,0x5b,0xe9,0x1f,0x0c,0x85,0xb9,0x15,0xd3,0x03,0x6f,0x6d,0xd7,0x30,0x1d,0x9c,0x2f,0x63,0x0e,0xdd,0xcc,0x2e,0x15,0x31,0x89,0x76,0x96,0xb6,0xd0,0x51,0x58,0x7a,0x63,0xa8,0x6b,0xb7,0xdf,0x52,0x39,0xef,0x0e,0xa0,0x49,0x7d,0xd3,0x6d,0xc7,0xe4,0x06,0x21,0x17,0x44,0x44,0x6c,0x69,0x7f,0x8d,0x92,0x80,0xd6,0x53,0xfb,0x26,0x3f,0x4d,0x69,0xa4,0x9e,0x73,0xb4,0xb0,0x4b,0x86,0x2e,0x11,0x97,0xc6,0x10},
+    {0xde,0x5f,0xbe,0x7d,0x27,0xc4,0x93,0x64,0xa2,0x7e,0xad,0x19,0xad,0x4f,0x5d,0x26,0x90,0x45,0x30,0x46,0xc8,0xdf,0x00,0x0e,0x09,0xfe,0x66,0xed,0xab,0x1c,0xe6,0x25,0x05,0xc8,0x58,0x83,0xa0,0x2a,0xa6,0x0c,0x47,0x42,0x20,0x7a,0xe3,0x4a,0x3d,0x6a,0xdc,0xed,0x11,0x3b,0xa6,0xd3,0x64,0x74,0xef,0x06,0x08,0x55,0xaf,0x9b,0xbf,0x03,0x04,0x66,0x58,0xcc,0x28,0xe1,0x13,0x3f,0x7e,0x74,0x59,0xb4,0xec,0x73,0x58,0x6f,0xf5,0x68,0x12,0xcc,0xed,0x3d,0xb6,0xa0,0x2c,0xe2,0x86,0x45,0x63,0x78,0x6d,0x56},
+    {0x34,0x08,0xc1,0x9c,0x9f,0xa4,0x37,0x16,0x51,0xc4,0x9b,0xa8,0xd5,0x56,0x8e,0xbc,0xdb,0xd2,0x7f,0x7f,0x0f,0xec,0xb5,0x1c,0xd9,0x35,0xcc,0x5e,0xca,0x5b,0x97,0x33,0xd0,0x2f,0x5a,0xc6,0x85,0x42,0x05,0xa1,0xc3,0x67,0x16,0xf3,0x2a,0x11,0x64,0x6c,0x58,0xee,0x1a,0x73,0x40,0xe2,0x0a,0x68,0x2a,0xb2,0x93,0x47,0xf3,0xa5,0xfb,0x14,0xd4,0xf7,0x85,0x69,0x16,0x46,0xd7,0x3c,0x57,0x00,0xc8,0xc9,0x84,0x5e,0x3e,0x59,0x1e,0x13,0x61,0x7b,0xb6,0xf2,0xc3,0x2f,0x6c,0x52,0xfc,0x83,0xea,0x9c,0x82,0x14},
+    {0xc2,0x95,0xdd,0x97,0x84,0x7b,0x43,0xff,0xa7,0xb5,0x4e,0xaa,0x30,0x4e,0x74,0x6c,0x8b,0xe8,0x85,0x3c,0x61,0x5d,0x0c,0x9e,0x73,0x81,0x75,0x5f,0x1e,0xc7,0xd9,0x2f,0xb8,0xec,0x71,0x4e,0x2f,0x0b,0xe7,0x21,0xe3,0x77,0xa4,0x40,0xb9,0xdd,0x56,0xe6,0x80,0x4f,0x1d,0xce,0xce,0x56,0x65,0xbf,0x7e,0x7b,0x5d,0x53,0xc4,0x3b,0xfc,0x05,0xdd,0xde,0xaf,0x52,0xae,0xb3,0xb8,0x24,0xcf,0x30,0x3b,0xed,0x8c,0x63,0x95,0x34,0x95,0x81,0xbe,0xa9,0x83,0xbc,0xa4,0x33,0x04,0x1f,0x65,0x5c,0x47,0x67,0x37,0x37},
+    {0xd9,0xad,0xd1,0x40,0xfd,0x99,0xba,0x2f,0x27,0xd0,0xf4,0x96,0x6f,0x16,0x07,0xb3,0xae,0x3b,0xf0,0x15,0x52,0xf0,0x63,0x43,0x99,0xf9,0x18,0x3b,0x6c,0xa5,0xbe,0x1f,0x90,0x65,0x24,0x14,0xcb,0x95,0x40,0x63,0x35,0x55,0xc1,0x16,0x40,0x14,0x12,0xef,0x60,0xbc,0x10,0x89,0x0c,0x14,0x38,0x9e,0x8c,0x7c,0x90,0x30,0x57,0x90,0xf5,0x6b,0x8a,0x5b,0x41,0xe1,0xf1,0x78,0xa7,0x0f,0x7e,0xa7,0xc3,0xba,0xf7,0x9f,0x40,0x06,0x50,0x9a,0xa2,0x9a,0xb8,0xd7,0x52,0x6f,0x56,0x5a,0x63,0x7a,0xf6,0x1c,0x52,0x02},
+    {0x94,0x52,0x9d,0x0a,0x0b,0xee,0x3f,0x51,0x66,0x5a,0xdf,0x0f,0x5c,0xe7,0x98,0x8f,0xce,0x07,0xe1,0xbf,0x88,0x86,0x61,0xd4,0xed,0x2c,0x38,0x71,0x7e,0x0a,0xa0,0x3f,0xe4,0x5e,0x2f,0x77,0x20,0x67,0x14,0xb1,0xce,0x9a,0x07,0x96,0xb1,0x94,0xf8,0xe8,0x4a,0x82,0xac,0x00,0x4d,0x22,0xf8,0x4a,0xc4,0x6c,0xcd,0xf7,0xd9,0x53,0x17,0x00,0x34,0xdb,0x3d,0x96,0x2d,0x23,0x69,0x3c,0x58,0x38,0x97,0xb4,0xda,0x87,0xde,0x1d,0x85,0xf2,0x91,0xa0,0xf9,0xd1,0xd7,0xaa,0xb6,0xed,0x48,0xa0,0x2f,0xfe,0xb5,0x12},
+    {0x4d,0xe3,0xfc,0x96,0xc4,0xfb,0xf0,0x71,0xed,0x5b,0xf3,0xad,0x6b,0x82,0xb9,0x73,0x61,0xc5,0x28,0xff,0x61,0x72,0x04,0xd2,0x6f,0x20,0xb1,0x6f,0xf9,0x76,0x9b,0x74,0x92,0x1e,0x6f,0xad,0x26,0x7c,0x2b,0xdf,0x13,0x89,0x4b,0x50,0x23,0xd3,0x66,0x4b,0xc3,0x8b,0x1c,0x75,0xc0,0x9d,0x40,0x8c,0xb8,0xc7,0x96,0x07,0xc2,0x93,0x7e,0x6f,0x05,0xae,0xa6,0xae,0x04,0xf6,0x5a,0x1f,0x99,0x9c,0xe4,0xbe,0xf1,0x51,0x23,0xc1,0x66,0x6b,0xff,0xee,0xb5,0x08,0xa8,0x61,0x51,0x21,0xe0,0x01,0x0f,0xc1,0xce,0x0f},
+    {0x44,0x1e,0xfe,0x49,0xa6,0x58,0x4d,0x64,0x7e,0x77,0xad,0x31,0xa2,0xae,0xfc,0x21,0xd2,0xd0,0x7f,0x88,0x5a,0x1c,0x44,0x02,0xf3,0x11,0xc5,0x83,0x71,0xaa,0x01,0x49,0x45,0x4e,0x24,0xc4,0x9d,0xd2,0xf2,0x3d,0x0a,0xde,0xd8,0x93,0x74,0x0e,0x02,0x2b,0x4d,0x21,0x0c,0x82,0x7e,0x06,0xc8,0x6c,0x0a,0xb9,0xea,0x6f,0x16,0x79,0x37,0x41,0xf0,0xf8,0x1a,0x8c,0x54,0xb7,0xb1,0x08,0xb4,0x99,0x62,0x24,0x7c,0x7a,0x0f,0xce,0x39,0xd9,0x06,0x1e,0xf9,0xb0,0x60,0xf7,0x13,0x12,0x6d,0x72,0x7b,0x88,0xbb,0x41},
+    {0xbe,0x46,0x43,0x74,0x44,0x7d,0xe8,0x40,0x25,0x2b,0xb5,0x15,0xd4,0xda,0x48,0x1d,0x3e,0x60,0x3b,0xa1,0x18,0x8a,0x3a,0x7c,0xf7,0xbd,0xcd,0x2f,0xc1,0x28,0xb7,0x4e,0xae,0x91,0x66,0x7c,0x59,0x4c,0x23,0x7e,0xc8,0xb4,0x85,0x0a,0x3d,0x9d,0x88,0x64,0xe7,0xfa,0x4a,0x35,0x0c,0xc9,0xe2,0xda,0x1d,0x9e,0x6a,0x0c,0x07,0x1e,0x87,0x0a,0x89,0x89,0xbc,0x4b,0x99,0xb5,0x01,0x33,0x60,0x42,0xdd,0x5b,0x3a,0xae,0x6b,0x73,0x3c,0x9e,0xd5,0x19,0xe2,0xad,0x61,0x0d,0x64,0xd4,0x85,0x26,0x0f,0x30,0xe7,0x3e},
+    {0xb7,0xd6,0x7d,0x9e,0xe4,0x55,0xd2,0xf5,0xac,0x1e,0x0b,0x61,0x5c,0x11,0x16,0x80,0xca,0x87,0xe1,0x92,0x5d,0x97,0x99,0x3c,0xc2,0x25,0x91,0x97,0x62,0x57,0x81,0x13,0x18,0x75,0x1e,0x84,0x47,0x79,0xfa,0x43,0xd7,0x46,0x9c,0x63,0x59,0xfa,0xc6,0xe5,0x74,0x2b,0x05,0xe3,0x1d,0x5e,0x06,0xa1,0x30,0x90,0xb8,0xcf,0xa2,0xc6,0x47,0x7d,0xe0,0xd6,0xf0,0x8e,0x14,0xd0,0xda,0x3f,0x3c,0x6f,0x54,0x91,0x9a,0x74,0x3e,0x9d,0x57,0x81,0xbb,0x26,0x10,0x62,0xec,0x71,0x80,0xec,0xc9,0x34,0x8d,0xf5,0x8c,0x14},
+    {0x27,0xf0,0x34,0x79,0xf6,0x92,0xa4,0x46,0xa9,0x0a,0x84,0xf6,0xbe,0x84,0x99,0x46,0x54,0x18,0x61,0x89,0x2a,0xbc,0xa1,0x5c,0xd4,0xbb,0x5d,0xbd,0x1e,0xfa,0xf2,0x3f,0x6d,0x75,0xe4,0x9a,0x7d,0x2f,0x57,0xe2,0x7f,0x48,0xf3,0x88,0xbb,0x45,0xc3,0x56,0x8d,0xa8,0x60,0x69,0x6d,0x0b,0xd1,0x9f,0xb9,0xa1,0xae,0x4e,0xad,0xeb,0x8f,0x27,0x66,0x39,0x93,0x8c,0x1f,0x68,0xaa,0xb1,0x98,0x0c,0x29,0x20,0x9c,0x94,0x21,0x8c,0x52,0x3c,0x9d,0x21,0x91,0x52,0x11,0x39,0x7b,0x67,0x9c,0xfe,0x02,0xdd,0x04,0x41},
+    {0x2a,0x42,0x24,0x11,0x5e,0xbf,0xb2,0x72,0xb5,0x3a,0xa3,0x98,0x33,0x0c,0xfa,0xa1,0x66,0xb6,0x52,0xfa,0x01,0x61,0xcb,0x94,0xd5,0x53,0xaf,0xaf,0x00,0x3b,0x86,0x2c,0xb8,0x6a,0x09,0xdb,0x06,0x4e,0x21,0x81,0x35,0x4f,0xe4,0x0c,0xc9,0xb6,0xa8,0x21,0xf5,0x2a,0x9e,0x40,0x2a,0xc1,0x24,0x65,0x81,0xa4,0xfc,0x8e,0xa4,0xb5,0x65,0x01,0x76,0x6a,0x84,0xa0,0x74,0xa4,0x90,0xf1,0xc0,0x7c,0x2f,0xcd,0x84,0xf9,0xef,0x12,0x8f,0x2b,0xaa,0x58,0x06,0x29,0x5e,0x69,0xb8,0xc8,0xfe,0xbf,0xd9,0x67,0x1b,0x59},
+    {0xfa,0x9b,0xb4,0x80,0x1c,0x0d,0x2f,0x31,0x8a,0xec,0xf3,0xab,0x5e,0x51,0x79,0x59,0x88,0x1c,0xf0,0x9e,0xc0,0x33,0x70,0x72,0xcb,0x7b,0x8f,0xca,0xc7,0x2e,0xe0,0x3d,0x5d,0xb5,0x18,0x9f,0x71,0xb3,0xb9,0x99,0x1e,0x64,0x8c,0xa1,0xfa,0xe5,0x65,0xe4,0xed,0x05,0x9f,0xc2,0x36,0x11,0x08,0x61,0x8b,0x12,0x30,0x70,0x86,0x4f,0x9b,0x48,0xef,0x92,0xeb,0x3a,0x2d,0x10,0x32,0xd2,0x61,0xa8,0x16,0x61,0xb4,0x53,0x62,0xe1,0x24,0xaa,0x0b,0x19,0xe7,0xab,0x7e,0x3d,0xbf,0xbe,0x6c,0x49,0xba,0xfb,0xf5,0x49},
+    {0xd4,0xcf,0x5b,0x8a,0x10,0x9a,0x94,0x30,0xeb,0x73,0x64,0xbc,0x70,0xdd,0x40,0xdc,0x1c,0x0d,0x7c,0x30,0xc1,0x94,0xc2,0x92,0x74,0x6e,0xfa,0xcb,0x6d,0xa8,0x04,0x56,0x2e,0x57,0x9c,0x1e,0x8c,0x62,0x5d,0x15,0x41,0x47,0x88,0xc5,0xac,0x86,0x4d,0x8a,0xeb,0x63,0x57,0x51,0xf6,0x52,0xa3,0x91,0x5b,0x51,0x67,0x88,0xc2,0xa6,0xa1,0x06,0xb6,0x64,0x17,0x7c,0xd4,0xd1,0x88,0x72,0x51,0x8b,0x41,0xe0,0x40,0x11,0x54,0x72,0xd1,0xf6,0xac,0x18,0x60,0x1a,0x03,0x9f,0xc6,0x42,0x27,0xfe,0x89,0x9e,0x98,0x20},
+    {0x7f,0xcc,0x2d,0x3a,0xfd,0x77,0x97,0x49,0x92,0xd8,0x4f,0xa5,0x2c,0x7c,0x85,0x32,0xa0,0xe3,0x07,0xd2,0x64,0xd8,0x79,0xa2,0x29,0x7e,0xa6,0x0c,0x1d,0xed,0x03,0x04,0x2e,0xec,0xea,0x85,0x8b,0x27,0x74,0x16,0xdf,0x2b,0xcb,0x7a,0x07,0xdc,0x21,0x56,0x5a,0xf4,0xcb,0x61,0x16,0x4c,0x0a,0x64,0xd3,0x95,0x05,0xf7,0x50,0x99,0x0b,0x73,0x52,0xc5,0x4e,0x87,0x35,0x2d,0x4b,0xc9,0x8d,0x6f,0x24,0x98,0xcf,0xc8,0xe6,0xc5,0xce,0x35,0xc0,0x16,0xfa,0x46,0xcb,0xf7,0xcc,0x3d,0x30,0x08,0x43,0x45,0xd7,0x5b},
+    {0xc2,0x4c,0xb2,0x28,0x95,0xd1,0x9a,0x7f,0x81,0xc1,0x35,0x63,0x65,0x54,0x6b,0x7f,0x36,0x72,0xc0,0x4f,0x6e,0xb6,0xb8,0x66,0x83,0xad,0x80,0x73,0x00,0x78,0x3a,0x13,0x2a,0x79,0xe7,0x15,0x21,0x93,0xc4,0x85,0xc9,0xdd,0xcd,0xbd,0xa2,0x89,0x4c,0xc6,0x62,0xd7,0xa3,0xad,0xa8,0x3d,0x1e,0x9d,0x2c,0xf8,0x67,0x30,0x12,0xdb,0xb7,0x5b,0xbe,0x62,0xca,0xc6,0x67,0xf4,0x61,0x09,0xee,0x52,0x19,0x21,0xd6,0x21,0xec,0x04,0x70,0x47,0xd5,0x9b,0x77,0x60,0x23,0x18,0xd2,0xe0,0xf0,0x58,0x6d,0xca,0x0d,0x74},
+    {0x4e,0xce,0xcf,0x52,0x07,0xee,0x48,0xdf,0xb7,0x08,0xec,0x06,0xf3,0xfa,0xff,0xc3,0xc4,0x59,0x54,0xb9,0x2a,0x0b,0x71,0x05,0x8d,0xa3,0x3e,0x96,0xfa,0x25,0x1d,0x16,0x3c,0x43,0x78,0x04,0x57,0x8c,0x1a,0x23,0x9d,0x43,0x81,0xc2,0x0e,0x27,0xb5,0xb7,0x9f,0x07,0xd9,0xe3,0xea,0x99,0xaa,0xdb,0xd9,0x03,0x2b,0x6c,0x25,0xf5,0x03,0x2c,0x7d,0xa4,0x53,0x7b,0x75,0x18,0x0f,0x79,0x79,0x58,0x0c,0xcf,0x30,0x01,0x7b,0x30,0xf9,0xf7,0x7e,0x25,0x77,0x3d,0x90,0x31,0xaf,0xbb,0x96,0xbd,0xbd,0x68,0x94,0x69},
+    {0xcf,0xfe,0xda,0xf4,0x46,0x2f,0x1f,0xbd,0xf7,0xd6,0x7f,0xa4,0x14,0x01,0xef,0x7c,0x7f,0xb3,0x47,0x4a,0xda,0xfd,0x1f,0xd3,0x85,0x57,0x90,0x73,0xa4,0x19,0x52,0x52,0x48,0x19,0xa9,0x6a,0xe6,0x3d,0xdd,0xd8,0xcc,0xd2,0xc0,0x2f,0xc2,0x64,0x50,0x48,0x2f,0xea,0xfd,0x34,0x66,0x24,0x48,0x9b,0x3a,0x2e,0x4a,0x6c,0x4e,0x1c,0x3e,0x29,0xe1,0x12,0x51,0x92,0x4b,0x13,0x6e,0x37,0xa0,0x5d,0xa1,0xdc,0xb5,0x78,0x37,0x70,0x11,0x31,0x1c,0x46,0xaf,0x89,0x45,0xb0,0x23,0x28,0x03,0x7f,0x44,0x5c,0x60,0x5b},
+    {0x89,0x7c,0xc4,0x20,0x59,0x80,0x65,0xb9,0xcc,0x8f,0x3b,0x92,0x0c,0x10,0xf0,0xe7,0x77,0xef,0xe2,0x02,0x65,0x25,0x01,0x00,0xee,0xb3,0xae,0xa8,0xce,0x6d,0xa7,0x24,0x4c,0xf0,0xe7,0xf0,0xc6,0xfe,0xe9,0x3b,0x62,0x49,0xe3,0x75,0x9e,0x57,0x6a,0x86,0x1a,0xe6,0x1d,0x1e,0x16,0xef,0x42,0x55,0xd5,0xbd,0x5a,0xcc,0xf4,0xfe,0x12,0x2f,0x40,0xc7,0xc0,0xdf,0xb2,0x22,0x45,0x0a,0x07,0xa4,0xc9,0x40,0x7f,0x6e,0xd0,0x10,0x68,0xf6,0xcf,0x78,0x41,0x14,0xcf,0xc6,0x90,0x37,0xa4,0x18,0x25,0x7b,0x60,0x5e},
+    {0x18,0x18,0xdf,0x6c,0x8f,0x1d,0xb3,0x58,0xa2,0x58,0x62,0xc3,0x4f,0xa7,0xcf,0x35,0x6e,0x1d,0xe6,0x66,0x4f,0xff,0xb3,0xe1,0xf7,0xd5,0xcd,0x6c,0xab,0xac,0x67,0x50,0x14,0xcf,0x96,0xa5,0x1c,0x43,0x2c,0xa0,0x00,0xe4,0xd3,0xae,0x40,0x2d,0xc4,0xe3,0xdb,0x26,0x0f,0x2e,0x80,0x26,0x45,0xd2,0x68,0x70,0x45,0x9e,0x13,0x33,0x1f,0x20,0x51,0x9d,0x03,0x08,0x6b,0x7f,0x52,0xfd,0x06,0x00,0x7c,0x01,0x64,0x49,0xb1,0x18,0xa8,0xa4,0x25,0x2e,0xb0,0x0e,0x22,0xd5,0x75,0x03,0x46,0x62,0x88,0xba,0x7c,0x39},
+    {0xb2,0x59,0x59,0xf0,0x93,0x30,0xc1,0x30,0x76,0x79,0xa9,0xe9,0x8d,0xa1,0x3a,0xe2,0x26,0x5e,0x1d,0x72,0x91,0xd4,0x2f,0x22,0x3a,0x6c,0x6e,0x76,0x20,0xd3,0x39,0x23,0xe7,0x79,0x13,0xc8,0xfb,0xc3,0x15,0x78,0xf1,0x2a,0xe1,0xdd,0x20,0x94,0x61,0xa6,0xd5,0xfd,0xa8,0x85,0xf8,0xc0,0xa9,0xff,0x52,0xc2,0xe1,0xc1,0x22,0x40,0x1b,0x77,0xa7,0x2f,0x3a,0x51,0x86,0xd9,0x7d,0xd8,0x08,0xcf,0xd4,0xf9,0x71,0x9b,0xac,0xf5,0xb3,0x83,0xa2,0x1e,0x1b,0xc3,0x6b,0xd0,0x76,0x1a,0x97,0x19,0x92,0x18,0x1a,0x33},
+    {0xc6,0x80,0x4f,0xfb,0x45,0x6f,0x16,0xf5,0xcf,0x75,0xc7,0x61,0xde,0xc7,0x36,0x9c,0x1c,0xd9,0x41,0x90,0x1b,0xe8,0xd4,0xe3,0x21,0xfe,0xbd,0x83,0x6b,0x7c,0x16,0x31,0xaf,0x72,0x75,0x9d,0x3a,0x2f,0x51,0x26,0x9e,0x4a,0x07,0x68,0x88,0xe2,0xcb,0x5b,0xc4,0xf7,0x80,0x11,0xc1,0xc1,0xed,0x84,0x7b,0xa6,0x49,0xf6,0x9f,0x61,0xc9,0x1a,0x68,0x10,0x4b,0x52,0x42,0x38,0x2b,0xf2,0x87,0xe9,0x9c,0xee,0x3b,0x34,0x68,0x50,0xc8,0x50,0x62,0x4a,0x84,0x71,0x9d,0xfc,0x11,0xb1,0x08,0x1f,0x34,0x36,0x24,0x61},
+    {0x8d,0x89,0x4e,0x87,0xdb,0x41,0x9d,0xd9,0x20,0xdc,0x07,0x6c,0xf1,0xa5,0xfe,0x09,0xbc,0x9b,0x0f,0xd0,0x67,0x2c,0x3d,0x79,0x40,0xff,0x5e,0x9e,0x30,0xe2,0xeb,0x46,0x38,0x26,0x2d,0x1a,0xe3,0x49,0x63,0x8b,0x35,0xfd,0xd3,0x9b,0x00,0xb7,0xdf,0x9d,0xa4,0x6b,0xa0,0xa3,0xb8,0xf1,0x8b,0x7f,0x45,0x04,0xd9,0x78,0x31,0xaa,0x22,0x15,0x38,0x49,0x61,0x69,0x53,0x2f,0x38,0x2c,0x10,0x6d,0x2d,0xb7,0x9a,0x40,0xfe,0xda,0x27,0xf2,0x46,0xb6,0x91,0x33,0xc8,0xe8,0x6c,0x30,0x24,0x05,0xf5,0x70,0xfe,0x45},
+    {0x8c,0x0b,0x0c,0x96,0xa6,0x75,0x48,0xda,0x20,0x2f,0x0e,0xef,0x76,0xd0,0x68,0x5b,0xd4,0x8f,0x0b,0x3d,0xcf,0x51,0xfb,0x07,0xd4,0x92,0xe3,0xa0,0x23,0x16,0x8d,0x42,0x91,0x14,0x95,0xc8,0x20,0x49,0xf2,0x62,0xa2,0x0c,0x63,0x3f,0xc8,0x07,0xf0,0x05,0xb8,0xd4,0xc9,0xf5,0xd2,0x45,0xbb,0x6f,0x45,0x22,0x7a,0xb5,0x6d,0x9f,0x61,0x16,0xfd,0x08,0xa3,0x01,0x44,0x4a,0x4f,0x08,0xac,0xca,0xa5,0x76,0xc3,0x19,0x22,0xa8,0x7d,0xbc,0xd1,0x43,0x46,0xde,0xb8,0xde,0xc6,0x38,0xbd,0x60,0x2d,0x59,0x81,0x1d},
+    {0x5f,0xac,0x0d,0xa6,0x56,0x87,0x36,0x61,0x57,0xdc,0xab,0xeb,0x6a,0x2f,0xe0,0x17,0x7d,0x0f,0xce,0x4c,0x2d,0x3f,0x19,0x7f,0xf0,0xdc,0xec,0x89,0x77,0x4a,0x23,0x20,0xe8,0xc5,0x85,0x7b,0x9f,0xb6,0x65,0x87,0xb2,0xba,0x68,0xd1,0x8b,0x67,0xf0,0x6f,0x9b,0x0f,0x33,0x1d,0x7c,0xe7,0x70,0x3a,0x7c,0x8e,0xaf,0xb0,0x51,0x6d,0x5f,0x3a,0x52,0xb2,0x78,0x71,0xb6,0x0d,0xd2,0x76,0x60,0xd1,0x1e,0xd5,0xf9,0x34,0x1c,0x07,0x70,0x11,0xe4,0xb3,0x20,0x4a,0x2a,0xf6,0x66,0xe3,0xff,0x3c,0x35,0x82,0xd6,0x7c},
+    {0xb6,0xfa,0x87,0xd8,0x5b,0xa4,0xe1,0x0b,0x6e,0x3b,0x40,0xba,0x32,0x6a,0x84,0x2a,0x00,0x60,0x6e,0xe9,0x12,0x10,0x92,0xd9,0x43,0x09,0xdc,0x3b,0x86,0xc8,0x38,0x28,0xf3,0xf4,0xac,0x68,0x60,0xcd,0x65,0xa6,0xd3,0xe3,0xd7,0x3c,0x18,0x2d,0xd9,0x42,0xd9,0x25,0x60,0x33,0x9d,0x38,0x59,0x57,0xff,0xd8,0x2c,0x2b,0x3b,0x25,0xf0,0x3e,0x30,0x50,0x46,0x4a,0xcf,0xb0,0x6b,0xd1,0xab,0x77,0xc5,0x15,0x41,0x6b,0x49,0xfa,0x9d,0x41,0xab,0xf4,0x8a,0xae,0xcf,0x82,0x12,0x28,0xa8,0x06,0xa6,0xb8,0xdc,0x21},
+    {0xc8,0x9f,0x9d,0x8c,0x46,0x04,0x60,0x5c,0xcb,0xa3,0x2a,0xd4,0x6e,0x09,0x40,0x25,0x9c,0x2f,0xee,0x12,0x4c,0x4d,0x5b,0x12,0xab,0x1d,0xa3,0x94,0x81,0xd0,0xc3,0x0b,0xba,0x31,0x77,0xbe,0xfa,0x00,0x8d,0x9a,0x89,0x18,0x9e,0x62,0x7e,0x60,0x03,0x82,0x7f,0xd9,0xf3,0x43,0x37,0x02,0xcc,0xb2,0x8b,0x67,0x6f,0x6c,0xbf,0x0d,0x84,0x5d,0x8b,0xe1,0x9f,0x30,0x0d,0x38,0x6e,0x70,0xc7,0x65,0xe1,0xb9,0xa6,0x2d,0xb0,0x6e,0xab,0x20,0xae,0x7d,0x99,0xba,0xbb,0x57,0xdd,0x96,0xc1,0x2a,0x23,0x76,0x42,0x3a},
+    {0xfa,0x84,0x70,0x8a,0x2c,0x43,0x42,0x4b,0x45,0xe5,0xb9,0xdf,0xe3,0x19,0x8a,0x89,0x5d,0xe4,0x58,0x9c,0x21,0x00,0x9f,0xbe,0xd1,0xeb,0x6d,0xa1,0xce,0x77,0xf1,0x1f,0xcb,0x7e,0x44,0xdb,0x72,0xc1,0xf8,0x3b,0xbd,0x2d,0x28,0xc6,0x1f,0xc4,0xcf,0x5f,0xfe,0x15,0xaa,0x75,0xc0,0xff,0xac,0x80,0xf9,0xa9,0xe1,0x24,0xe8,0xc9,0x70,0x07,0xfd,0xb5,0xb5,0x45,0x9a,0xd9,0x61,0xcf,0x24,0x79,0x3a,0x1b,0xe9,0x84,0x09,0x86,0x89,0x3e,0x3e,0x30,0x19,0x09,0x30,0xe7,0x1e,0x0b,0x50,0x41,0xfd,0x64,0xf2,0x39},
+    {0x9c,0xe2,0xe7,0xdb,0x17,0x34,0xad,0xa7,0x9c,0x13,0x9c,0x2b,0x6a,0x37,0x94,0xbd,0xa9,0x7b,0x59,0x93,0x8e,0x1b,0xe9,0xa0,0x40,0x98,0x88,0x68,0x34,0xd7,0x12,0x17,0xe1,0x7b,0x09,0xfe,0xab,0x4a,0x9b,0xd1,0x29,0x19,0xe0,0xdf,0xe1,0xfc,0x6d,0xa4,0xff,0xf1,0xa6,0x2c,0x94,0x08,0xc9,0xc3,0x4e,0xf1,0x35,0x2c,0x27,0x21,0xc6,0x65,0xdd,0x93,0x31,0xce,0xf8,0x89,0x2b,0xe7,0xbb,0xc0,0x25,0xa1,0x56,0x33,0x10,0x4d,0x83,0xfe,0x1c,0x2e,0x3d,0xa9,0x19,0x04,0x72,0xe2,0x9c,0xb1,0x0a,0x80,0xf9,0x22},
+    {0xcb,0xf8,0x9e,0x3e,0x8a,0x36,0x5a,0x60,0x15,0x47,0x50,0xa5,0x22,0xc0,0xe9,0xe3,0x8f,0x24,0x24,0x5f,0xb0,0x48,0x3d,0x55,0xe5,0x26,0x76,0x64,0xcd,0x16,0xf4,0x13,0xac,0xfd,0x6e,0x9a,0xdd,0x9f,0x02,0x42,0x41,0x49,0xa5,0x34,0xbe,0xce,0x12,0xb9,0x7b,0xf3,0xbd,0x87,0xb9,0x64,0x0f,0x64,0xb4,0xca,0x98,0x85,0xd3,0xa4,0x71,0x41,0x8c,0x4c,0xc9,0x99,0xaa,0x58,0x27,0xfa,0x07,0xb8,0x00,0xb0,0x6f,0x6f,0x00,0x23,0x92,0x53,0xda,0xad,0xdd,0x91,0xd2,0xfb,0xab,0xd1,0x4b,0x57,0xfa,0x14,0x82,0x50},
+    {0x4b,0xfe,0xd6,0x3e,0x15,0x69,0x02,0xc2,0xc4,0x77,0x1d,0x51,0x39,0x67,0x5a,0xa6,0x94,0xaf,0x14,0x2c,0x46,0x26,0xde,0xcb,0x4b,0xa7,0xab,0x6f,0xec,0x60,0xf9,0x22,0xd6,0x03,0xd0,0x53,0xbb,0x15,0x1a,0x46,0x65,0xc9,0xf3,0xbc,0x88,0x28,0x10,0xb2,0x5a,0x3a,0x68,0x6c,0x75,0x76,0xc5,0x27,0x47,0xb4,0x6c,0xc8,0xa4,0x58,0x77,0x3a,0x76,0x50,0xae,0x93,0xf6,0x11,0x81,0x54,0xa6,0x54,0xfd,0x1d,0xdf,0x21,0xae,0x1d,0x65,0x5e,0x11,0xf3,0x90,0x8c,0x24,0x12,0x94,0xf4,0xe7,0x8d,0x5f,0xd1,0x9f,0x5d},
+    {0x7f,0x72,0x63,0x6d,0xd3,0x08,0x14,0x03,0x33,0xb5,0xc7,0xd7,0xef,0x9a,0x37,0x6a,0x4b,0xe2,0xae,0xcc,0xc5,0x8f,0xe1,0xa9,0xd3,0xbe,0x8f,0x4f,0x91,0x35,0x2f,0x33,0x1e,0x52,0xd7,0xee,0x2a,0x4d,0x24,0x3f,0x15,0x96,0x2e,0x43,0x28,0x90,0x3a,0x8e,0xd4,0x16,0x9c,0x2e,0x77,0xba,0x64,0xe1,0xd8,0x98,0xeb,0x47,0xfa,0x87,0xc1,0x3b,0x0c,0xc2,0x86,0xea,0x15,0x01,0x47,0x6d,0x25,0xd1,0x46,0x6c,0xcb,0xb7,0x8a,0x99,0x88,0x01,0x66,0x3a,0xb5,0x32,0x78,0xd7,0x03,0xba,0x6f,0x90,0xce,0x81,0x0d,0x45},
+    {0x75,0x52,0x20,0xa6,0xa1,0xb6,0x7b,0x6e,0x83,0x8e,0x3c,0x41,0xd7,0x21,0x4f,0xaa,0xb2,0x5c,0x8f,0xe8,0x55,0xd1,0x56,0x6f,0xe1,0x5b,0x34,0xa6,0x4b,0x5d,0xe2,0x2d,0x3f,0x74,0xae,0x1c,0x96,0xd8,0x74,0xd0,0xed,0x63,0x1c,0xee,0xf5,0x18,0x6d,0xf8,0x29,0xed,0xf4,0xe7,0x5b,0xc5,0xbd,0x97,0x08,0xb1,0x3a,0x66,0x79,0xd2,0xba,0x4c,0xcd,0x1f,0xd7,0xa0,0x24,0x90,0xd1,0x80,0xf8,0x8a,0x28,0xfb,0x0a,0xc2,0x25,0xc5,0x19,0x64,0x3a,0x5f,0x4b,0x97,0xa3,0xb1,0x33,0x72,0x00,0xe2,0xef,0xbc,0x7f,0x7d},
+    {0x01,0x28,0x6b,0x26,0x6a,0x1e,0xef,0xfa,0x16,0x9f,0x73,0xd5,0xc4,0x68,0x6c,0x86,0x2c,0x76,0x03,0x1b,0xbc,0x2f,0x8a,0xf6,0x8d,0x5a,0xb7,0x87,0x5e,0x43,0x75,0x59,0x94,0x90,0xc2,0xf3,0xc5,0x5d,0x7c,0xcd,0xab,0x05,0x91,0x2a,0x9a,0xa2,0x81,0xc7,0x58,0x30,0x1c,0x42,0x36,0x1d,0xc6,0x80,0xd7,0xd4,0xd8,0xdc,0x96,0xd1,0x9c,0x4f,0x68,0x37,0x7b,0x6a,0xd8,0x97,0x92,0x19,0x63,0x7a,0xd1,0x1a,0x24,0x58,0xd0,0xd0,0x17,0x0c,0x1c,0x5c,0xad,0x9c,0x02,0xba,0x07,0x03,0x7a,0x38,0x84,0xd0,0xcd,0x7c},
+    {0x17,0x04,0x26,0x6d,0x2c,0x42,0xa6,0xdc,0xbd,0x40,0x82,0x94,0x50,0x3d,0x15,0xae,0x77,0xc6,0x68,0xfb,0xb4,0xc1,0xc0,0xa9,0x53,0xcf,0xd0,0x61,0xed,0xd0,0x8b,0x42,0x93,0xcc,0x60,0x67,0x18,0x84,0x0c,0x9b,0x99,0x2a,0xb3,0x1a,0x7a,0x00,0xae,0xcd,0x18,0xda,0x0b,0x62,0x86,0xec,0x8d,0xa8,0x44,0xca,0x90,0x81,0x84,0xca,0x93,0x35,0xa7,0x9a,0x84,0x5e,0x9a,0x18,0x13,0x92,0xcd,0xfa,0xd8,0x65,0x35,0xc3,0xd8,0xd4,0xd1,0xbb,0xfd,0x53,0x5b,0x54,0x52,0x8c,0xe6,0x63,0x2d,0xda,0x08,0x83,0x39,0x27},
+    {0x13,0xd4,0x5e,0x43,0x28,0x8d,0xc3,0x42,0xc9,0xcc,0x78,0x32,0x60,0xf3,0x50,0xbd,0xef,0x03,0xda,0x79,0x1a,0xab,0x07,0xbb,0x55,0x33,0x8c,0xbe,0xae,0x97,0x95,0x26,0x53,0x24,0x70,0x0a,0x4c,0x0e,0xa1,0xb9,0xde,0x1b,0x7d,0xd5,0x66,0x58,0xa2,0x0f,0xf7,0xda,0x27,0xcd,0xb5,0xd9,0xb9,0xff,0xfd,0x33,0x2c,0x49,0x45,0x29,0x2c,0x57,0xbe,0x30,0xcd,0xd6,0x45,0xc7,0x7f,0xc7,0xfb,0xae,0xba,0xe3,0xd3,0xe8,0xdf,0xe4,0x0c,0xda,0x5d,0xaa,0x30,0x88,0x2c,0xa2,0x80,0xca,0x5b,0xc0,0x98,0x54,0x98,0x7f},
+    {0x17,0xe1,0x0b,0x9f,0x88,0xce,0x49,0x38,0x88,0xa2,0x54,0x7b,0x1b,0xad,0x05,0x80,0x1c,0x92,0xfc,0x23,0x9f,0xc3,0xa3,0x3d,0x04,0xf3,0x31,0x0a,0x47,0xec,0xc2,0x76,0x63,0x63,0xbf,0x0f,0x52,0x15,0x56,0xd3,0xa6,0xfb,0x4d,0xcf,0x45,0x5a,0x04,0x08,0xc2,0xa0,0x3f,0x87,0xbc,0x4f,0xc2,0xee,0xe7,0x12,0x9b,0xd6,0x3c,0x65,0xf2,0x30,0x85,0x0c,0xc1,0xaa,0x38,0xc9,0x08,0x8a,0xcb,0x6b,0x27,0xdb,0x60,0x9b,0x17,0x46,0x70,0xac,0x6f,0x0e,0x1e,0xc0,0x20,0xa9,0xda,0x73,0x64,0x59,0xf1,0x73,0x12,0x2f},
+    {0x11,0x1e,0xe0,0x8a,0x7c,0xfc,0x39,0x47,0x9f,0xab,0x6a,0x4a,0x90,0x74,0x52,0xfd,0x2e,0x8f,0x72,0x87,0x82,0x8a,0xd9,0x41,0xf2,0x69,0x5b,0xd8,0x2a,0x57,0x9e,0x5d,0xc0,0x0b,0xa7,0x55,0xd7,0x8b,0x48,0x30,0xe7,0x42,0xd4,0xf1,0xa4,0xb5,0xd6,0x06,0x62,0x61,0x59,0xbc,0x9e,0xa6,0xd1,0xea,0x84,0xf7,0xc5,0xed,0x97,0x19,0xac,0x38,0x3b,0xb1,0x51,0xa7,0x17,0xb5,0x66,0x06,0x8c,0x85,0x9b,0x7e,0x86,0x06,0x7d,0x74,0x49,0xde,0x4d,0x45,0x11,0xc0,0xac,0xac,0x9c,0xe6,0xe9,0xbf,0x9c,0xcd,0xdf,0x22},
+    {0xd9,0x0c,0x0d,0xc3,0xe0,0xd2,0xdb,0x8d,0x33,0x43,0xbb,0xac,0x5f,0x66,0x8e,0xad,0x1f,0x96,0x2a,0x32,0x8c,0x25,0x6b,0x8f,0xc7,0xc1,0x48,0x54,0xc0,0x16,0x29,0x6b,0xa1,0xe0,0x3b,0x10,0xb4,0x59,0xec,0x56,0x69,0xf9,0x59,0xd2,0xec,0xba,0xe3,0x2e,0x32,0xcd,0xf5,0x13,0x94,0xb2,0x7c,0x79,0x72,0xe4,0xcd,0x24,0x78,0x87,0xe9,0x0f,0x3b,0x91,0xba,0x0a,0xd1,0x34,0xdb,0x7e,0x0e,0xac,0x6d,0x2e,0x82,0xcd,0xa3,0x4e,0x15,0xf8,0x78,0x65,0xff,0x3d,0x08,0x66,0x17,0x0a,0xf0,0x7f,0x30,0x3f,0x30,0x4c},
+    {0x85,0x8c,0xb2,0x17,0xd6,0x3b,0x0a,0xd3,0xea,0x3b,0x77,0x39,0xb7,0x77,0xd3,0xc5,0xbf,0x5c,0x6a,0x1e,0x8c,0xe7,0xc6,0xc6,0xc4,0xb7,0x2a,0x8b,0xf7,0xb8,0x61,0x0d,0x00,0x45,0xd9,0x0d,0x58,0x03,0xfc,0x29,0x93,0xec,0xbb,0x6f,0xa4,0x7a,0xd2,0xec,0xf8,0xa7,0xe2,0xc2,0x5f,0x15,0x0a,0x13,0xd5,0xa1,0x06,0xb7,0x1a,0x15,0x6b,0x41,0xb0,0x36,0xc1,0xe9,0xef,0xd7,0xa8,0x56,0x20,0x4b,0xe4,0x58,0xcd,0xe5,0x07,0xbd,0xab,0xe0,0x57,0x1b,0xda,0x2f,0xe6,0xaf,0xd2,0xe8,0x77,0x42,0xf7,0x2a,0x1a,0x19},
+    {0x31,0x14,0x3c,0xc5,0x4b,0xf7,0x16,0xce,0xde,0xed,0x72,0x20,0xce,0x25,0x97,0x2b,0xe7,0x3e,0xb2,0xb5,0x6f,0xc3,0xb9,0xb8,0x08,0xc9,0x5c,0x0b,0x45,0x0e,0x2e,0x7e,0xfb,0x0e,0x46,0x4f,0x43,0x2b,0xe6,0x9f,0xd6,0x07,0x36,0xa6,0xd4,0x03,0xd3,0xde,0x24,0xda,0xa0,0xb7,0x0e,0x21,0x52,0xf0,0x93,0x5b,0x54,0x00,0xbe,0x7d,0x7e,0x23,0x30,0xb4,0x01,0x67,0xed,0x75,0x35,0x01,0x10,0xfd,0x0b,0x9f,0xe6,0x94,0x10,0x23,0x22,0x7f,0xe4,0x83,0x15,0x0f,0x32,0x75,0xe3,0x55,0x11,0xb1,0x99,0xa6,0xaf,0x71},
+    {0x1d,0xb6,0x53,0x39,0x9b,0x6f,0xce,0x65,0xe6,0x41,0xa1,0xaf,0xea,0x39,0x58,0xc6,0xfe,0x59,0xf7,0xa9,0xfd,0x5f,0x43,0x0f,0x8e,0xc2,0xb1,0xc2,0xe9,0x42,0x11,0x02,0xd6,0x50,0x3b,0x47,0x1c,0x3c,0x42,0xea,0x10,0xef,0x38,0x3b,0x1f,0x7a,0xe8,0x51,0x95,0xbe,0xc9,0xb2,0x5f,0xbf,0x84,0x9b,0x1c,0x9a,0xf8,0x78,0xbc,0x1f,0x73,0x00,0x80,0x18,0xf8,0x48,0x18,0xc7,0x30,0xe4,0x19,0xc1,0xce,0x5e,0x22,0x0c,0x96,0xbf,0xe3,0x15,0xba,0x6b,0x83,0xe0,0xda,0xb6,0x08,0x58,0xe1,0x47,0x33,0x6f,0x4d,0x4c},
+    {0xc9,0x1f,0x7d,0xc1,0xcf,0xec,0xf7,0x18,0x14,0x3c,0x40,0x51,0xa6,0xf5,0x75,0x6c,0xdf,0x0c,0xee,0xf7,0x2b,0x71,0xde,0xdb,0x22,0x7a,0xe4,0xa7,0xaa,0xdd,0x3f,0x19,0x70,0x19,0x8f,0x98,0xfc,0xdd,0x0c,0x2f,0x1b,0xf5,0xb9,0xb0,0x27,0x62,0x91,0x6b,0xbe,0x76,0x91,0x77,0xc4,0xb6,0xc7,0x6e,0xa8,0x9f,0x8f,0xa8,0x00,0x95,0xbf,0x38,0x6f,0x87,0xe8,0x37,0x3c,0xc9,0xd2,0x1f,0x2c,0x46,0xd1,0x18,0x5a,0x1e,0xf6,0xa2,0x76,0x12,0x24,0x39,0x82,0xf5,0x80,0x50,0x69,0x49,0x0d,0xbf,0x9e,0xb9,0x6f,0x6a},
+    {0xeb,0x55,0x08,0x56,0xbb,0xc1,0x46,0x6a,0x9d,0xf0,0x93,0xf8,0x38,0xbb,0x16,0x24,0xc1,0xac,0x71,0x8f,0x37,0x11,0x1d,0xd7,0xea,0x96,0x18,0xa3,0x14,0x69,0xf7,0x75,0xc6,0x23,0xe4,0xb6,0xb5,0x22,0xb1,0xee,0x8e,0xff,0x86,0xf2,0x10,0x70,0x9d,0x93,0x8c,0x5d,0xcf,0x1d,0x83,0x2a,0xa9,0x90,0x10,0xeb,0xc5,0x42,0x9f,0xda,0x6f,0x13,0xd1,0xbd,0x05,0xa3,0xb1,0xdf,0x4c,0xf9,0x08,0x2c,0xf8,0x9f,0x9d,0x4b,0x36,0x0f,0x8a,0x58,0xbb,0xc3,0xa5,0xd8,0x87,0x2a,0xba,0xdc,0xe8,0x0b,0x51,0x83,0x21,0x02},
+    {0x14,0x2d,0xad,0x5e,0x38,0x66,0xf7,0x4a,0x30,0x58,0x7c,0xca,0x80,0xd8,0x8e,0xa0,0x3d,0x1e,0x21,0x10,0xe6,0xa6,0x13,0x0d,0x03,0x6c,0x80,0x7b,0xe1,0x1c,0x07,0x6a,0x7f,0x7a,0x30,0x43,0x01,0x71,0x5a,0x9d,0x5f,0xa4,0x7d,0xc4,0x9e,0xde,0x63,0xb0,0xd3,0x7a,0x92,0xbe,0x52,0xfe,0xbb,0x22,0x6c,0x42,0x40,0xfd,0x41,0xc4,0x87,0x13,0xf8,0x8a,0x97,0x87,0xd1,0xc3,0xd3,0xb5,0x13,0x44,0x0e,0x7f,0x3d,0x5a,0x2b,0x72,0xa0,0x7c,0x47,0xbb,0x48,0x48,0x7b,0x0d,0x92,0xdc,0x1e,0xaf,0x6a,0xb2,0x71,0x31},
+    {0xa8,0x4c,0x56,0x97,0x90,0x31,0x2f,0xa9,0x19,0xe1,0x75,0x22,0x4c,0xb8,0x7b,0xff,0x50,0x51,0x87,0xa4,0x37,0xfe,0x55,0x4f,0x5a,0x83,0xf0,0x3c,0x87,0xd4,0x1f,0x22,0xd1,0x47,0x8a,0xb2,0xd8,0xb7,0x0d,0xa6,0xf1,0xa4,0x70,0x17,0xd6,0x14,0xbf,0xa6,0x58,0xbd,0xdd,0x53,0x93,0xf8,0xa1,0xd4,0xe9,0x43,0x42,0x34,0x63,0x4a,0x51,0x6c,0x41,0x63,0x15,0x3a,0x4f,0x20,0x22,0x23,0x2d,0x03,0x0a,0xba,0xe9,0xe0,0x73,0xfb,0x0e,0x03,0x0f,0x41,0x4c,0xdd,0xe0,0xfc,0xaa,0x4a,0x92,0xfb,0x96,0xa5,0xda,0x48},
+    {0xc7,0x9c,0xa5,0x5c,0x66,0x8e,0xca,0x6e,0xa0,0xac,0x38,0x2e,0x4b,0x25,0x47,0xa8,0xce,0x17,0x1e,0xd2,0x08,0xc7,0xaf,0x31,0xf7,0x4a,0xd8,0xca,0xfc,0xd6,0x6d,0x67,0x93,0x97,0x4c,0xc8,0x5d,0x1d,0xf6,0x14,0x06,0x82,0x41,0xef,0xe3,0xf9,0x41,0x99,0xac,0x77,0x62,0x34,0x8f,0xb8,0xf5,0xcd,0xa9,0x79,0x8a,0x0e,0xfa,0x37,0xc8,0x58,0x58,0x90,0xfc,0x96,0x85,0x68,0xf9,0x0c,0x1b,0xa0,0x56,0x7b,0xf3,0xbb,0xdc,0x1d,0x6a,0xd6,0x35,0x49,0x7d,0xe7,0xc2,0xdc,0x0a,0x7f,0xa5,0xc6,0xf2,0x73,0x4f,0x1c},
+    {0xbb,0xa0,0x5f,0x30,0xbd,0x4f,0x7a,0x0e,0xad,0x63,0xc6,0x54,0xe0,0x4c,0x9d,0x82,0x48,0x38,0xe3,0x2f,0x83,0xc3,0x21,0xf4,0x42,0x4c,0xf6,0x1b,0x0d,0xc8,0x5a,0x79,0x84,0x34,0x7c,0xfc,0x6e,0x70,0x6e,0xb3,0x61,0xcf,0xc1,0xc3,0xb4,0xc9,0xdf,0x73,0xe5,0xc7,0x1c,0x78,0xc9,0x79,0x1d,0xeb,0x5c,0x67,0xaf,0x7d,0xdb,0x9a,0x45,0x70,0xb3,0x2b,0xb4,0x91,0x49,0xdb,0x91,0x1b,0xca,0xdc,0x02,0x4b,0x23,0x96,0x26,0x57,0xdc,0x78,0x8c,0x1f,0xe5,0x9e,0xdf,0x9f,0xd3,0x1f,0xe2,0x8c,0x84,0x62,0xe1,0x5f},
+    {0x1a,0x96,0x94,0xe1,0x4f,0x21,0x59,0x4e,0x4f,0xcd,0x71,0x0d,0xc7,0x7d,0xbe,0x49,0x2d,0xf2,0x50,0x3b,0xd2,0xcf,0x00,0x93,0x32,0x72,0x91,0xfc,0x46,0xd4,0x89,0x47,0x08,0xb2,0x7c,0x5d,0x2d,0x85,0x79,0x28,0xe7,0xf2,0x7d,0x68,0x70,0xdd,0xde,0xb8,0x91,0x78,0x68,0x21,0xab,0xff,0x0b,0xdc,0x35,0xaa,0x7d,0x67,0x43,0xc0,0x44,0x2b,0x8e,0xb7,0x4e,0x07,0xab,0x87,0x1c,0x1a,0x67,0xf4,0xda,0x99,0x8e,0xd1,0xc6,0xfa,0x67,0x90,0x4f,0x48,0xcd,0xbb,0xac,0x3e,0xe4,0xa4,0xb9,0x2b,0xef,0x2e,0xc5,0x60},
+    {0xf1,0x8b,0xfd,0x3b,0xbc,0x89,0x5d,0x0b,0x1a,0x55,0xf3,0xc9,0x37,0x92,0x6b,0xb0,0xf5,0x28,0x30,0xd5,0xb0,0x16,0x4c,0x0e,0xab,0xca,0xcf,0x2c,0x31,0x9c,0xbc,0x10,0x11,0x6d,0xae,0x7c,0xc2,0xc5,0x2b,0x70,0xab,0x8c,0xa4,0x54,0x9b,0x69,0xc7,0x44,0xb2,0x2e,0x49,0xba,0x56,0x40,0xbc,0xef,0x6d,0x67,0xb6,0xd9,0x48,0x72,0xd7,0x70,0x5b,0xa0,0xc2,0x3e,0x4b,0xe8,0x8a,0xaa,0xe0,0x81,0x17,0xed,0xf4,0x9e,0x69,0x98,0xd1,0x85,0x8e,0x70,0xe4,0x13,0x45,0x79,0x13,0xf4,0x76,0xa9,0xd3,0x5b,0x75,0x63},
+    {0x53,0x08,0xd1,0x2a,0x3e,0xa0,0x5f,0xb5,0x69,0x35,0xe6,0x9e,0x90,0x75,0x6f,0x35,0x90,0xb8,0x69,0xbe,0xfd,0xf1,0xf9,0x9f,0x84,0x6f,0xc1,0x8b,0xc4,0xc1,0x8c,0x0d,0xb7,0xac,0xf1,0x97,0x18,0x10,0xc7,0x3d,0xd8,0xbb,0x65,0xc1,0x5e,0x7d,0xda,0x5d,0x0f,0x02,0xa1,0x0f,0x9c,0x5b,0x8e,0x50,0x56,0x2a,0xc5,0x37,0x17,0x75,0x63,0x27,0xa9,0x19,0xb4,0x6e,0xd3,0x02,0x94,0x02,0xa5,0x60,0xb4,0x77,0x7e,0x4e,0xb4,0xf0,0x56,0x49,0x3c,0xd4,0x30,0x62,0xa8,0xcf,0xe7,0x66,0xd1,0x7a,0x8a,0xdd,0xc2,0x70},
+    {0x0e,0xec,0x6f,0x9f,0x50,0x94,0x61,0x65,0x8d,0x51,0xc6,0x46,0xa9,0x7e,0x2e,0xee,0x5c,0x9b,0xe0,0x67,0xf3,0xc1,0x33,0x97,0x95,0x84,0x94,0x63,0x63,0xac,0x0f,0x2e,0x13,0x7e,0xed,0xb8,0x7d,0x96,0xd4,0x91,0x7a,0x81,0x76,0xd7,0x0a,0x2f,0x25,0x74,0x64,0x25,0x85,0x0d,0xe0,0x82,0x09,0xe4,0xe5,0x3c,0xa5,0x16,0x38,0x61,0xb8,0x32,0x64,0xcd,0x48,0xe4,0xbe,0xf7,0xe7,0x79,0xd0,0x86,0x78,0x08,0x67,0x3a,0xc8,0x6a,0x2e,0xdb,0xe4,0xa0,0xd9,0xd4,0x9f,0xf8,0x41,0x4f,0x5a,0x73,0x5c,0x21,0x79,0x41},
+    {0x2a,0xed,0xdc,0xd7,0xe7,0x94,0x70,0x8c,0x70,0x9c,0xd3,0x47,0xc3,0x8a,0xfb,0x97,0x02,0xd9,0x06,0xa9,0x33,0xe0,0x3b,0xe1,0x76,0x9d,0xd9,0x0c,0xa3,0x44,0x03,0x70,0x34,0xcd,0x6b,0x28,0xb9,0x33,0xae,0xe4,0xdc,0xd6,0x9d,0x55,0xb6,0x7e,0xef,0xb7,0x1f,0x8e,0xd3,0xb3,0x1f,0x14,0x8b,0x27,0x86,0xc2,0x41,0x22,0x66,0x85,0xfa,0x31,0xf4,0x22,0x36,0x2e,0x42,0x6c,0x82,0xaf,0x2d,0x50,0x33,0x98,0x87,0x29,0x20,0xc1,0x23,0x91,0x38,0x2b,0xe1,0xb7,0xc1,0x9b,0x89,0x24,0x95,0xa9,0x12,0x23,0xbb,0x24},
+    {0xc3,0x67,0xde,0x32,0x17,0xed,0xa8,0xb1,0x48,0x49,0x1b,0x46,0x18,0x94,0xb4,0x3c,0xd2,0xbc,0xcf,0x76,0x43,0x43,0xbd,0x8e,0x08,0x80,0x18,0x1e,0x87,0x3e,0xee,0x0f,0x6b,0x5c,0xf8,0xf5,0x2a,0x0c,0xf8,0x41,0x94,0x67,0xfa,0x04,0xc3,0x84,0x72,0x68,0xad,0x1b,0xba,0xa3,0x99,0xdf,0x45,0x89,0x16,0x5d,0xeb,0xff,0xf9,0x2a,0x1d,0x0d,0xdf,0x1e,0x62,0x32,0xa1,0x8a,0xda,0xa9,0x79,0x65,0x22,0x59,0xa1,0x22,0xb8,0x30,0x93,0xc1,0x9a,0xa7,0x7b,0x19,0x04,0x40,0x76,0x1d,0x53,0x18,0x97,0xd7,0xac,0x16},
+    {0x3d,0x1d,0x9b,0x2d,0xaf,0x72,0xdf,0x72,0x5a,0x24,0x32,0xa4,0x36,0x2a,0x46,0x63,0x37,0x96,0xb3,0x16,0x79,0xa0,0xce,0x3e,0x09,0x23,0x30,0xb9,0xf6,0x0e,0x3e,0x12,0xad,0xb6,0x87,0x78,0xc5,0xc6,0x59,0xc9,0xba,0xfe,0x90,0x5f,0xad,0x9e,0xe1,0x94,0x04,0xf5,0x42,0xa3,0x62,0x4e,0xe2,0x16,0x00,0x17,0x16,0x18,0x4b,0xd3,0x4e,0x16,0x9a,0xe6,0x2f,0x19,0x4c,0xd9,0x7e,0x48,0x13,0x15,0x91,0x3a,0xea,0x2c,0xae,0x61,0x27,0xde,0xa4,0xb9,0xd3,0xf6,0x7b,0x87,0xeb,0xf3,0x73,0x10,0xc6,0x0f,0xda,0x78},
+    {0x6a,0xc6,0x2b,0xe5,0x28,0x5d,0xf1,0x5b,0x8e,0x1a,0xf0,0x70,0x18,0xe3,0x47,0x2c,0xdd,0x8b,0xc2,0x06,0xbc,0xaf,0x19,0x24,0x3a,0x17,0x6b,0x25,0xeb,0xde,0x25,0x2d,0x94,0x3a,0x0c,0x68,0xf1,0x80,0x9f,0xa2,0xe6,0xe7,0xe9,0x1a,0x15,0x7e,0xf7,0x71,0x73,0x79,0x01,0x48,0x58,0xf1,0x00,0x11,0xdd,0x8d,0xb3,0x16,0xb3,0xa4,0x4a,0x05,0xb8,0x7c,0x26,0x19,0x8d,0x46,0xc8,0xdf,0xaf,0x4d,0xe5,0x66,0x9c,0x78,0x28,0x0b,0x17,0xec,0x6e,0x66,0x2a,0x1d,0xeb,0x2a,0x60,0xa7,0x7d,0xab,0xa6,0x10,0x46,0x13},
+    {0xfe,0xb0,0xf6,0x8d,0xc7,0x8e,0x13,0x51,0x1b,0xf5,0x75,0xe5,0x89,0xda,0x97,0x53,0xb9,0xf1,0x7a,0x71,0x1d,0x7a,0x20,0x09,0x50,0xd6,0x20,0x2b,0xba,0xfd,0x02,0x21,0x15,0xf5,0xd1,0x77,0xe7,0x65,0x2a,0xcd,0xf1,0x60,0xaa,0x8f,0x87,0x91,0x89,0x54,0xe5,0x06,0xbc,0xda,0xbc,0x3b,0xb7,0xb1,0xfb,0xc9,0x7c,0xa9,0xcb,0x78,0x48,0x65,0xa1,0xe6,0x5c,0x05,0x05,0xe4,0x9e,0x96,0x29,0xad,0x51,0x12,0x68,0xa7,0xbc,0x36,0x15,0xa4,0x7d,0xaa,0x17,0xf5,0x1a,0x3a,0xba,0xb2,0xec,0x29,0xdb,0x25,0xd7,0x0a},
+    {0x57,0x24,0x4e,0x83,0xb1,0x67,0x42,0xdc,0xc5,0x1b,0xce,0x70,0xb5,0x44,0x75,0xb6,0xd7,0x5e,0xd1,0xf7,0x0b,0x7a,0xf0,0x1a,0x50,0x36,0xa0,0x71,0xfb,0xcf,0xef,0x4a,0x85,0x6f,0x05,0x9b,0x0c,0xbc,0xc7,0xfe,0xd7,0xff,0xf5,0xe7,0x68,0x52,0x7d,0x53,0xfa,0xae,0x12,0x43,0x62,0xc6,0xaf,0x77,0xd9,0x9f,0x39,0x02,0x53,0x5f,0x67,0x4f,0x1e,0x17,0x15,0x04,0x36,0x36,0x2d,0xc3,0x3b,0x48,0x98,0x89,0x11,0xef,0x2b,0xcd,0x10,0x51,0x94,0xd0,0xad,0x6e,0x0a,0x87,0x61,0x65,0xa8,0xa2,0x72,0xbb,0xcc,0x0b},
+    {0xc8,0xa9,0xb1,0xea,0x2f,0x96,0x5e,0x18,0xcd,0x7d,0x14,0x65,0x35,0xe6,0xe7,0x86,0xf2,0x6d,0x5b,0xbb,0x31,0xe0,0x92,0xb0,0x3e,0xb7,0xd6,0x59,0xab,0xf0,0x24,0x40,0x96,0x12,0xfe,0x50,0x4c,0x5e,0x6d,0x18,0x7e,0x9f,0xe8,0xfe,0x82,0x7b,0x39,0xe0,0xb0,0x31,0x70,0x50,0xc5,0xf6,0xc7,0x3b,0xc2,0x37,0x8f,0x10,0x69,0xfd,0x78,0x66,0xc2,0x63,0x68,0x63,0x31,0xfa,0x86,0x15,0xf2,0x33,0x2d,0x57,0x48,0x8c,0xf6,0x07,0xfc,0xae,0x9e,0x78,0x9f,0xcc,0x73,0x4f,0x01,0x47,0xad,0x8e,0x10,0xe2,0x42,0x2d},
+    {0x9b,0xd2,0xdf,0x94,0x15,0x13,0xf5,0x97,0x6a,0x4c,0x3f,0x31,0x5d,0x98,0x55,0x61,0x10,0x50,0x45,0x08,0x07,0x3f,0xa1,0xeb,0x22,0xd3,0xd2,0xb8,0x08,0x26,0x6b,0x67,0x93,0x75,0x53,0x0f,0x0d,0x7b,0x71,0x21,0x4c,0x06,0x1e,0x13,0x0b,0x69,0x4e,0x91,0x9f,0xe0,0x2a,0x75,0xae,0x87,0xb6,0x1b,0x6e,0x3c,0x42,0x9b,0xa7,0xf3,0x0b,0x42,0x47,0x2b,0x5b,0x1c,0x65,0xba,0x38,0x81,0x80,0x1b,0x1b,0x31,0xec,0xb6,0x71,0x86,0xb0,0x35,0x31,0xbc,0xb1,0x0c,0xff,0x7b,0xe0,0xf1,0x0c,0x9c,0xfa,0x2f,0x5d,0x74},
+    {0xbd,0xc8,0xc9,0x2b,0x1e,0x5a,0x52,0xbf,0x81,0x9d,0x47,0x26,0x08,0x26,0x5b,0xea,0xdb,0x55,0x01,0xdf,0x0e,0xc7,0x11,0xd5,0xd0,0xf5,0x0c,0x96,0xeb,0x3c,0xe2,0x1a,0x6a,0x4e,0xd3,0x21,0x57,0xdf,0x36,0x60,0xd0,0xb3,0x7b,0x99,0x27,0x88,0xdb,0xb1,0xfa,0x6a,0x75,0xc8,0xc3,0x09,0xc2,0xd3,0x39,0xc8,0x1d,0x4c,0xe5,0x5b,0xe1,0x06,0x4a,0x99,0x32,0x19,0x87,0x5d,0x72,0x5b,0xb0,0xda,0xb1,0xce,0xb5,0x1c,0x35,0x32,0x05,0xca,0xb7,0xda,0x49,0x15,0xc4,0x7d,0xf7,0xc1,0x8e,0x27,0x61,0xd8,0xde,0x58},
+    {0x5c,0xc5,0x66,0xf2,0x93,0x37,0x17,0xd8,0x49,0x4e,0x45,0xcc,0xc5,0x76,0xc9,0xc8,0xa8,0xc3,0x26,0xbc,0xf8,0x82,0xe3,0x5c,0xf9,0xf6,0x85,0x54,0xe8,0x9d,0xf3,0x2f,0xa8,0xc9,0xc2,0xb6,0xa8,0x5b,0xfb,0x2d,0x8c,0x59,0x2c,0xf5,0x8e,0xef,0xee,0x48,0x73,0x15,0x2d,0xf1,0x07,0x91,0x80,0x33,0xd8,0x5b,0x1d,0x53,0x6b,0x69,0xba,0x08,0x7a,0xc5,0xef,0xc3,0xee,0x3e,0xed,0x77,0x11,0x48,0xff,0xd4,0x17,0x55,0xe0,0x04,0xcb,0x71,0xa6,0xf1,0x3f,0x7a,0x3d,0xea,0x54,0xfe,0x7c,0x94,0xb4,0x33,0x06,0x12},
+    {0x42,0x00,0x61,0x91,0x78,0x98,0x94,0x0b,0xe8,0xfa,0xeb,0xec,0x3c,0xb1,0xe7,0x4e,0xc0,0xa4,0xf0,0x94,0x95,0x73,0xbe,0x70,0x85,0x91,0xd5,0xb4,0x99,0x0a,0xd3,0x35,0x0a,0x10,0x12,0x49,0x47,0x31,0xbd,0x82,0x06,0xbe,0x6f,0x7e,0x6d,0x7b,0x23,0xde,0xc6,0x79,0xea,0x11,0x19,0x76,0x1e,0xe1,0xde,0x3b,0x39,0xcb,0xe3,0x3b,0x43,0x07,0xf4,0x97,0xe9,0x5c,0xc0,0x44,0x79,0xff,0xa3,0x51,0x5c,0xb0,0xe4,0x3d,0x5d,0x57,0x7c,0x84,0x76,0x5a,0xfd,0x81,0x33,0x58,0x9f,0xda,0xf6,0x7a,0xde,0x3e,0x87,0x2d},
+    {0x09,0x34,0x37,0x43,0x64,0x31,0x7a,0x15,0xd9,0x81,0xaa,0xf4,0xee,0xb7,0xb8,0xfa,0x06,0x48,0xa6,0xf5,0xe6,0xfe,0x93,0xb0,0xb6,0xa7,0x7f,0x70,0x54,0x36,0x77,0x2e,0x81,0xf9,0x5d,0x4e,0xe1,0x02,0x62,0xaa,0xf5,0xe1,0x15,0x50,0x17,0x59,0x0d,0xa2,0x6c,0x1d,0xe2,0xba,0xd3,0x75,0xa2,0x18,0x53,0x02,0x60,0x01,0x8a,0x61,0x43,0x05,0xc1,0x23,0x4c,0x97,0xf4,0xbd,0xea,0x0d,0x93,0x46,0xce,0x9d,0x25,0x0a,0x6f,0xaa,0x2c,0xba,0x9a,0xa2,0xb8,0x2c,0x20,0x04,0x0d,0x96,0x07,0x2d,0x36,0x43,0x14,0x4b},
+    {0x7a,0x1f,0x6e,0xb6,0xc7,0xb7,0xc4,0xcc,0x7e,0x2f,0x0c,0xf5,0x25,0x7e,0x15,0x44,0x1c,0xaf,0x3e,0x71,0xfc,0x6d,0xf0,0x3e,0xf7,0x63,0xda,0x52,0x67,0x44,0x2f,0x58,0xcb,0x9c,0x52,0x1c,0xe9,0x54,0x7c,0x96,0xfb,0x35,0xc6,0x64,0x92,0x26,0xf6,0x30,0x65,0x19,0x12,0x78,0xf4,0xaf,0x47,0x27,0x5c,0x6f,0xf6,0xea,0x18,0x84,0x03,0x17,0xe4,0x4c,0x32,0x20,0xd3,0x7b,0x31,0xc6,0xc4,0x8b,0x48,0xa4,0xe8,0x42,0x10,0xa8,0x64,0x13,0x5a,0x4e,0x8b,0xf1,0x1e,0xb2,0xc9,0x8d,0xa2,0xcd,0x4b,0x1c,0x2a,0x0c},
+    {0x47,0x04,0x1f,0x6f,0xd0,0xc7,0x4d,0xd2,0x59,0xc0,0x87,0xdb,0x3e,0x9e,0x26,0xb2,0x8f,0xd2,0xb2,0xfb,0x72,0x02,0x5b,0xd1,0x77,0x48,0xf6,0xc6,0xd1,0x8b,0x55,0x7c,0x45,0x69,0xbd,0x69,0x48,0x81,0xc4,0xed,0x22,0x8d,0x1c,0xbe,0x7d,0x90,0x6d,0x0d,0xab,0xc5,0x5c,0xd5,0x12,0xd2,0x3b,0xc6,0x83,0xdc,0x14,0xa3,0x30,0x9b,0x6a,0x5a,0x3d,0x46,0x96,0xd3,0x24,0x15,0xec,0xd0,0xf0,0x24,0x5a,0xc3,0x8a,0x62,0xbb,0x12,0xa4,0x5f,0xbc,0x1c,0x79,0x3a,0x0c,0xa5,0xc3,0xaf,0xfb,0x0a,0xca,0xa5,0x04,0x04},
+    {0xd6,0x43,0xa7,0x0a,0x07,0x40,0x1f,0x8c,0xe8,0x5e,0x26,0x5b,0xcb,0xd0,0xba,0xcc,0xde,0xd2,0x8f,0x66,0x6b,0x04,0x4b,0x57,0x33,0x96,0xdd,0xca,0xfd,0x5b,0x39,0x46,0xd1,0x6f,0x41,0x2a,0x1b,0x9e,0xbc,0x62,0x8b,0x59,0x50,0xe3,0x28,0xf7,0xc6,0xb5,0x67,0x69,0x5d,0x3d,0xd8,0x3f,0x34,0x04,0x98,0xee,0xf8,0xe7,0x16,0x75,0x52,0x39,0x9c,0x9a,0x5d,0x1a,0x2d,0xdb,0x7f,0x11,0x2a,0x5c,0x00,0xd1,0xbc,0x45,0x77,0x9c,0xea,0x6f,0xd5,0x54,0xf1,0xbe,0xd4,0xef,0x16,0xd0,0x22,0xe8,0x29,0x9a,0x57,0x76},
+    {0x17,0x2a,0xc0,0x49,0x7e,0x8e,0xb6,0x45,0x7f,0xa3,0xa9,0xbc,0xa2,0x51,0xcd,0x23,0x1b,0x4c,0x22,0xec,0x11,0x5f,0xd6,0x3e,0xb1,0xbd,0x05,0x9e,0xdc,0x84,0xa3,0x43,0xf2,0x34,0xb4,0x52,0x13,0xb5,0x3c,0x33,0xe1,0x80,0xde,0x93,0x49,0x28,0x32,0xd8,0xce,0x35,0x0d,0x75,0x87,0x28,0x51,0xb5,0xc1,0x77,0x27,0x2a,0xbb,0x14,0xc5,0x02,0x45,0xb6,0xf1,0x8b,0xda,0xd5,0x4b,0x68,0x53,0x4b,0xb5,0xf6,0x7e,0xd3,0x8b,0xfb,0x53,0xd2,0xb0,0xa9,0xd7,0x16,0x39,0x31,0x59,0x80,0x54,0x61,0x09,0x92,0x60,0x11},
+    {0xaa,0xcf,0xda,0x29,0x69,0x16,0x4d,0xb4,0x8f,0x59,0x13,0x84,0x4c,0x9f,0x52,0xda,0x59,0x55,0x3d,0x45,0xca,0x63,0xef,0xe9,0x0b,0x8e,0x69,0xc5,0x5b,0x12,0x1e,0x35,0xcd,0x4d,0x9b,0x36,0x16,0x56,0x38,0x7a,0x63,0x35,0x5c,0x65,0xa7,0x2c,0xc0,0x75,0x21,0x80,0xf1,0xd4,0xf9,0x1b,0xc2,0x7d,0x42,0xe0,0xe6,0x91,0x74,0x7d,0x63,0x2f,0xbe,0x7b,0xf6,0x1a,0x46,0x9b,0xb4,0xd4,0x61,0x89,0xab,0xc8,0x7a,0x03,0x03,0xd6,0xfb,0x99,0xa6,0xf9,0x9f,0xe1,0xde,0x71,0x9a,0x2a,0xce,0xe7,0x06,0x2d,0x18,0x7f},
+    {0xec,0x68,0x01,0xab,0x64,0x8e,0x7c,0x7a,0x43,0xc5,0xed,0x15,0x55,0x4a,0x5a,0xcb,0xda,0x0e,0xcd,0x47,0xd3,0x19,0x55,0x09,0xb0,0x93,0x3e,0x34,0x8c,0xac,0xd4,0x67,0x22,0x75,0x21,0x8e,0x72,0x4b,0x45,0x09,0xd8,0xb8,0x84,0xd4,0xf4,0xe8,0x58,0xaa,0x3c,0x90,0x46,0x7f,0x4d,0x25,0x58,0xd3,0x17,0x52,0x1c,0x24,0x43,0xc0,0xac,0x44,0x77,0x57,0x7a,0x4f,0xbb,0x6b,0x7d,0x1c,0xe1,0x13,0x83,0x91,0xd4,0xfe,0x35,0x8b,0x84,0x46,0x6b,0xc9,0xc6,0xa1,0xdc,0x4a,0xbd,0x71,0xad,0x12,0x83,0x1c,0x6d,0x55},
+    {0x82,0x39,0x8d,0x0c,0xe3,0x40,0xef,0x17,0x34,0xfa,0xa3,0x15,0x3e,0x07,0xf7,0x31,0x6e,0x64,0x73,0x07,0xcb,0xf3,0x21,0x4f,0xff,0x4e,0x82,0x1d,0x6d,0x6c,0x6c,0x74,0x21,0xe8,0x1b,0xb1,0x56,0x67,0xf0,0x81,0xdd,0xf3,0xa3,0x10,0x23,0xf8,0xaf,0x0f,0x5d,0x46,0x99,0x6a,0x55,0xd0,0xb2,0xf8,0x05,0x7f,0x8c,0xcc,0x38,0xbe,0x7a,0x09,0xa4,0x2d,0xa5,0x7e,0x87,0xc9,0x49,0x0c,0x43,0x1d,0xdc,0x9b,0x55,0x69,0x43,0x4c,0xd2,0xeb,0xcc,0xf7,0x09,0x38,0x2c,0x02,0xbd,0x84,0xee,0x4b,0xa3,0x14,0x7e,0x57},
+    {0x0a,0x3b,0xa7,0x61,0xac,0x68,0xe2,0xf0,0xf5,0xa5,0x91,0x37,0x10,0xfa,0xfa,0xf2,0xe9,0x00,0x6d,0x6b,0x82,0x3e,0xe1,0xc1,0x42,0x8f,0xd7,0x6f,0xe9,0x7e,0xfa,0x60,0x2b,0xd7,0x4d,0xbd,0xbe,0xce,0xfe,0x94,0x11,0x22,0x0f,0x06,0xda,0x4f,0x6a,0xf4,0xff,0xd1,0xc8,0xc0,0x77,0x59,0x4a,0x12,0x95,0x92,0x00,0xfb,0xb8,0x04,0x53,0x70,0xc6,0x6e,0x29,0x4d,0x35,0x1d,0x3d,0xb6,0xd8,0x31,0xad,0x5f,0x3e,0x05,0xc3,0xf3,0xec,0x42,0xbd,0xb4,0x8c,0x95,0x0b,0x67,0xfd,0x53,0x63,0xa1,0x0c,0x8e,0x39,0x21},
+    {0xf3,0x33,0x2b,0x38,0x8a,0x05,0xf5,0x89,0xb4,0xc0,0x48,0xad,0x0b,0xba,0xe2,0x5a,0x6e,0xb3,0x3d,0xa5,0x03,0xb5,0x93,0x8f,0xe6,0x32,0xa2,0x95,0x9d,0xed,0xa3,0x5a,0x01,0x56,0xb7,0xb4,0xf9,0xaa,0x98,0x27,0x72,0xad,0x8d,0x5c,0x13,0x72,0xac,0x5e,0x23,0xa0,0xb7,0x61,0x61,0xaa,0xce,0xd2,0x4e,0x7d,0x8f,0xe9,0x84,0xb2,0xbf,0x1b,0x61,0x65,0xd9,0xc7,0xe9,0x77,0x67,0x65,0x36,0x80,0xc7,0x72,0x54,0x12,0x2b,0xcb,0xee,0x6e,0x50,0xd9,0x99,0x32,0x05,0x65,0xcc,0x57,0x89,0x5e,0x4e,0xe1,0x07,0x4a},
+    {0x99,0xf9,0x0d,0x98,0xcb,0x12,0xe4,0x4e,0x71,0xc7,0x6e,0x3c,0x6f,0xd7,0x15,0xa3,0xfd,0x77,0x5c,0x92,0xde,0xed,0xa5,0xbb,0x02,0x34,0x31,0x1d,0x39,0xac,0x0b,0x3f,0x9b,0xa4,0x77,0xc4,0xcd,0x58,0x0b,0x24,0x17,0xf0,0x47,0x64,0xde,0xda,0x38,0xfd,0xad,0x6a,0xc8,0xa7,0x32,0x8d,0x92,0x19,0x81,0xa0,0xaf,0x84,0xed,0x7a,0xaf,0x50,0xe5,0x5b,0xf6,0x15,0x01,0xde,0x4f,0x6e,0xb2,0x09,0x61,0x21,0x21,0x26,0x98,0x29,0xd9,0xd6,0xad,0x0b,0x81,0x05,0x02,0x78,0x06,0xd0,0xeb,0xba,0x16,0xa3,0x21,0x19},
+    {0xfc,0x70,0xb8,0xdf,0x7e,0x2f,0x42,0x89,0xbd,0xb3,0x76,0x4f,0xeb,0x6b,0x29,0x2c,0xf7,0x4d,0xc2,0x36,0xd4,0xf1,0x38,0x07,0xb0,0xae,0x73,0xe2,0x41,0xdf,0x58,0x64,0x8b,0xc1,0xf3,0xd9,0x9a,0xad,0x5a,0xd7,0x9c,0xc1,0xb1,0x60,0xef,0x0e,0x6a,0x56,0xd9,0x0e,0x5c,0x25,0xac,0x0b,0x9a,0x3e,0xf5,0xc7,0x62,0xa0,0xec,0x9d,0x04,0x7b,0x83,0x44,0x44,0x35,0x7a,0xe3,0xcb,0xdc,0x93,0xbe,0xed,0x0f,0x33,0x79,0x88,0x75,0x87,0xdd,0xc5,0x12,0xc3,0x04,0x60,0x78,0x64,0x0e,0x95,0xc2,0xcb,0xdc,0x93,0x60},
+    {0x6d,0x70,0xe0,0x85,0x85,0x9a,0xf3,0x1f,0x33,0x39,0xe7,0xb3,0xd8,0xa5,0xd0,0x36,0x3b,0x45,0x8f,0x71,0xe1,0xf2,0xb9,0x43,0x7c,0xa9,0x27,0x48,0x08,0xea,0xd1,0x57,0x4b,0x03,0x84,0x60,0xbe,0xee,0xde,0x6b,0x54,0xb8,0x0f,0x78,0xb6,0xc2,0x99,0x31,0x95,0x06,0x2d,0xb6,0xab,0x76,0x33,0x97,0x90,0x7d,0x64,0x8b,0xc9,0x80,0x31,0x6e,0x71,0xb0,0x28,0xa1,0xe7,0xb6,0x7a,0xee,0xaa,0x8b,0xa8,0x93,0x6d,0x59,0xc1,0xa4,0x30,0x61,0x21,0xb2,0x82,0xde,0xb4,0xf7,0x18,0xbd,0x97,0xdd,0x9d,0x99,0x3e,0x36},
+    {0xc4,0x1f,0xee,0x35,0xc1,0x43,0xa8,0x96,0xcf,0xc8,0xe4,0x08,0x55,0xb3,0x6e,0x97,0x30,0xd3,0x8c,0xb5,0x01,0x68,0x2f,0xb4,0x2b,0x05,0x3a,0x69,0x78,0x9b,0xee,0x48,0xc6,0xae,0x4b,0xe2,0xdc,0x48,0x18,0x2f,0x60,0xaf,0xbc,0xba,0x55,0x72,0x9b,0x76,0x31,0xe9,0xef,0x3c,0x6e,0x3c,0xcb,0x90,0x55,0xb3,0xf9,0xc6,0x9b,0x97,0x1f,0x23,0xc6,0xf3,0x2a,0xcc,0x4b,0xde,0x31,0x5c,0x1f,0x8d,0x20,0xfe,0x30,0xb0,0x4b,0xb0,0x66,0xb4,0x4f,0xc1,0x09,0x70,0x8d,0xb7,0x13,0x24,0x79,0x08,0x9b,0xfa,0x9b,0x07},
+    {0xf4,0x0d,0x30,0xda,0x51,0x3a,0x90,0xe3,0xb0,0x5a,0xa9,0x3d,0x23,0x64,0x39,0x84,0x80,0x64,0x35,0x0b,0x2d,0xf1,0x3c,0xed,0x94,0x71,0x81,0x84,0xf6,0x77,0x8c,0x03,0x45,0x42,0xd5,0xa2,0x80,0xed,0xc9,0xf3,0x52,0x39,0xf6,0x77,0x78,0x8b,0xa0,0x0a,0x75,0x54,0x08,0xd1,0x63,0xac,0x6d,0xd7,0x6b,0x63,0x70,0x94,0x15,0xfb,0xf4,0x1e,0xec,0x7b,0x16,0x5b,0xe6,0x5e,0x4e,0x85,0xc2,0xcd,0xd0,0x96,0x42,0x0a,0x59,0x59,0x99,0x21,0x10,0x98,0x34,0xdf,0xb2,0x72,0x56,0xff,0x0b,0x4a,0x2a,0xe9,0x5e,0x57},
+    {0xcf,0x2f,0x18,0x8a,0x90,0x80,0xc0,0xd4,0xbd,0x9d,0x48,0x99,0xc2,0x70,0xe1,0x30,0xde,0x33,0xf7,0x52,0x57,0xbd,0xba,0x05,0x00,0xfd,0xd3,0x2c,0x11,0xe7,0xd4,0x43,0x01,0xd8,0xa4,0x0a,0x45,0xbc,0x46,0x5d,0xd8,0xb9,0x33,0xa5,0x27,0x12,0xaf,0xc3,0xc2,0x06,0x89,0x2b,0x26,0x3b,0x9e,0x38,0x1b,0x58,0x2f,0x38,0x7e,0x1e,0x0a,0x20,0xc5,0x3a,0xf9,0xea,0x67,0xb9,0x8d,0x51,0xc0,0x52,0x66,0x05,0x9b,0x98,0xbc,0x71,0xf5,0x97,0x71,0x56,0xd9,0x85,0x2b,0xfe,0x38,0x4e,0x1e,0x65,0x52,0xca,0x0e,0x05},
+    {0x9c,0x0c,0x3f,0x45,0xde,0x1a,0x43,0xc3,0x9b,0x3b,0x70,0xff,0x5e,0x04,0xf5,0xe9,0x3d,0x7b,0x84,0xed,0xc9,0x7a,0xd9,0xfc,0xc6,0xf4,0x58,0x1c,0xc2,0xe6,0x0e,0x4b,0xea,0x68,0xe6,0x60,0x76,0x39,0xac,0x97,0x97,0xb4,0x3a,0x15,0xfe,0xbb,0x19,0x9b,0x9f,0xa7,0xec,0x34,0xb5,0x79,0xb1,0x4c,0x57,0xae,0x31,0xa1,0x9f,0xc0,0x51,0x61,0x96,0x5d,0xf0,0xfd,0x0d,0x5c,0xf5,0x3a,0x7a,0xee,0xb4,0x2a,0xe0,0x2e,0x26,0xdd,0x09,0x17,0x17,0x12,0x87,0xbb,0xb2,0x11,0x0b,0x03,0x0f,0x80,0xfa,0x24,0xef,0x1f},
+    {0x96,0x31,0xa7,0x1a,0xfb,0x53,0xd6,0x37,0x18,0x64,0xd7,0x3f,0x30,0x95,0x94,0x0f,0xb2,0x17,0x3a,0xfb,0x09,0x0b,0x20,0xad,0x3e,0x61,0xc8,0x2f,0x29,0x49,0x4d,0x54,0x86,0x6b,0x97,0x30,0xf5,0xaf,0xd2,0x22,0x04,0x46,0xd2,0xc2,0x06,0xb8,0x90,0x8d,0xe5,0xba,0xe5,0x4d,0x6c,0x89,0xa1,0xdc,0x17,0x0c,0x34,0xc8,0xe6,0x5f,0x00,0x28,0x88,0x86,0x52,0x34,0x9f,0xba,0xef,0x6a,0xa1,0x7d,0x10,0x25,0x94,0xff,0x1b,0x5c,0x36,0x4b,0xd9,0x66,0xcd,0xbb,0x5b,0xf7,0xfa,0x6d,0x31,0x0f,0x93,0x72,0xe4,0x72},
+    {0x4f,0x08,0x81,0x97,0x8c,0x20,0x95,0x26,0xe1,0x0e,0x45,0x23,0x0b,0x2a,0x50,0xb1,0x02,0xde,0xef,0x03,0xa6,0xae,0x9d,0xfd,0x4c,0xa3,0x33,0x27,0x8c,0x2e,0x9d,0x5a,0x27,0x76,0x2a,0xd3,0x35,0xf6,0xf3,0x07,0xf0,0x66,0x65,0x5f,0x86,0x4d,0xaa,0x7a,0x50,0x44,0xd0,0x28,0x97,0xe7,0x85,0x3c,0x38,0x64,0xe0,0x0f,0x00,0x7f,0xee,0x1f,0xe5,0xf7,0xdb,0x03,0xda,0x05,0x53,0x76,0xbd,0xcd,0x34,0x14,0x49,0xf2,0xda,0xa4,0xec,0x88,0x4a,0xd2,0xcd,0xd5,0x4a,0x7b,0x43,0x05,0x04,0xee,0x51,0x40,0xf9,0x00},
+    {0xb2,0x30,0xd3,0xc3,0x23,0x6b,0x35,0x8d,0x06,0x1b,0x47,0xb0,0x9b,0x8b,0x1c,0xf2,0x3c,0xb8,0x42,0x6e,0x6c,0x31,0x6c,0xb3,0x0d,0xb1,0xea,0x8b,0x7e,0x9c,0xd7,0x07,0x53,0x97,0xaf,0x07,0xbb,0x93,0xef,0xd7,0xa7,0x66,0xb7,0x3d,0xcf,0xd0,0x3e,0x58,0xc5,0x1e,0x0b,0x6e,0xbf,0x98,0x69,0xce,0x52,0x04,0xd4,0x5d,0xd2,0xff,0xb7,0x47,0x12,0xdd,0x08,0xbc,0x9c,0xfb,0xfb,0x87,0x9b,0xc2,0xee,0xe1,0x3a,0x6b,0x06,0x8a,0xbf,0xc1,0x1f,0xdb,0x2b,0x24,0x57,0x0d,0xb6,0x4b,0xa6,0x5e,0xa3,0x20,0x35,0x1c},
+    {0x4a,0xa3,0xcb,0xbc,0xa6,0x53,0xd2,0x80,0x9b,0x21,0x38,0x38,0xa1,0xc3,0x61,0x3e,0x96,0xe3,0x82,0x98,0x01,0xb6,0xc3,0x90,0x6f,0xe6,0x0e,0x5d,0x77,0x05,0x3d,0x1c,0x59,0xc0,0x6b,0x21,0x40,0x6f,0xa8,0xcd,0x7e,0xd8,0xbc,0x12,0x1d,0x23,0xbb,0x1f,0x90,0x09,0xc7,0x17,0x9e,0x6a,0x95,0xb4,0x55,0x2e,0xd1,0x66,0x3b,0x0c,0x75,0x38,0x1a,0xe5,0x22,0x94,0x40,0xf1,0x2e,0x69,0x71,0xf6,0x5d,0x2b,0x3c,0xc7,0xc0,0xcb,0x29,0xe0,0x4c,0x74,0xe7,0x4f,0x01,0x21,0x7c,0x48,0x30,0xd3,0xc7,0xe2,0x21,0x06},
+    {0x8d,0x83,0x59,0x82,0xcc,0x60,0x98,0xaf,0xdc,0x9a,0x9f,0xc6,0xc1,0x48,0xea,0x90,0x30,0x1e,0x58,0x65,0x37,0x48,0x26,0x65,0xbc,0xa5,0xd3,0x7b,0x09,0xd6,0x07,0x00,0xf3,0xf0,0xdb,0xb0,0x96,0x17,0xae,0xb7,0x96,0xe1,0x7c,0xe1,0xb9,0xaf,0xdf,0x54,0xb4,0xa3,0xaa,0xe9,0x71,0x30,0x92,0x25,0x9d,0x2e,0x00,0xa1,0x9c,0x58,0x8e,0x5d,0x4b,0xa9,0x42,0x08,0x95,0x1d,0xbf,0xc0,0x3e,0x2e,0x8f,0x58,0x63,0xc3,0xd3,0xb2,0xef,0xe2,0x51,0xbb,0x38,0x14,0x96,0x0a,0x86,0xbf,0x1c,0x3c,0x78,0xd7,0x83,0x15},
+    {0xe1,0x7a,0xa2,0x5d,0xef,0xa2,0xee,0xec,0x74,0x01,0x67,0x55,0x14,0x3a,0x7c,0x59,0x7a,0x16,0x09,0x66,0x12,0x2a,0xa6,0xc9,0x70,0x8f,0xed,0x81,0x2e,0x5f,0x2a,0x25,0xc7,0x28,0x9d,0xcc,0x04,0x47,0x03,0x90,0x8f,0xc5,0x2c,0xf7,0x9e,0x67,0x1b,0x1d,0x26,0x87,0x5b,0xbe,0x5f,0x2b,0xe1,0x16,0x0a,0x58,0xc5,0x83,0x4e,0x06,0x58,0x49,0x0d,0xe8,0x66,0x50,0x26,0x94,0x28,0x0d,0x6b,0x8c,0x7c,0x30,0x85,0xf7,0xc3,0xfc,0xfd,0x12,0x11,0x0c,0x78,0xda,0x53,0x1b,0x88,0xb3,0x43,0xd8,0x0b,0x17,0x9c,0x07},
+    {0xff,0x6f,0xfa,0x64,0xe4,0xec,0x06,0x05,0x23,0xe5,0x05,0x62,0x1e,0x43,0xe3,0xbe,0x42,0xea,0xb8,0x51,0x24,0x42,0x79,0x35,0x00,0xfb,0xc9,0x4a,0xe3,0x05,0xec,0x6d,0x56,0xd0,0xd5,0xc0,0x50,0xcd,0xd6,0xcd,0x3b,0x57,0x03,0xbb,0x6d,0x68,0xf7,0x9a,0x48,0xef,0xc3,0xf3,0x3f,0x72,0xa6,0x3c,0xcc,0x8a,0x7b,0x31,0xd7,0xc0,0x68,0x67,0xb3,0xc1,0x55,0xf1,0xe5,0x25,0xb6,0x94,0x91,0x7b,0x7b,0x99,0xa7,0xf3,0x7b,0x41,0x00,0x26,0x6b,0x6d,0xdc,0xbd,0x2c,0xc2,0xf4,0x52,0xcd,0xdd,0x14,0x5e,0x44,0x51},
+    {0x51,0x49,0x14,0x3b,0x4b,0x2b,0x50,0x57,0xb3,0xbc,0x4b,0x44,0x6b,0xff,0x67,0x8e,0xdb,0x85,0x63,0x16,0x27,0x69,0xbd,0xb8,0xc8,0x95,0x92,0xe3,0x31,0x6f,0x18,0x13,0x55,0xa4,0xbe,0x2b,0xab,0x47,0x31,0x89,0x29,0x91,0x07,0x92,0x4f,0xa2,0x53,0x8c,0xa7,0xf7,0x30,0xbe,0x48,0xf9,0x49,0x4b,0x3d,0xd4,0x4f,0x6e,0x08,0x90,0xe9,0x12,0x2e,0xbb,0xdf,0x7f,0xb3,0x96,0x0c,0xf1,0xf9,0xea,0x1c,0x12,0x5e,0x93,0x9a,0x9f,0x3f,0x98,0x5b,0x3a,0xc4,0x36,0x11,0xdf,0xaf,0x99,0x3e,0x5d,0xf0,0xe3,0xb2,0x77},
+    {0xde,0xc4,0x2e,0x9c,0xc5,0xa9,0x6f,0x29,0xcb,0xf3,0x84,0x4f,0xbf,0x61,0x8b,0xbc,0x08,0xf9,0xa8,0x17,0xd9,0x06,0x77,0x1c,0x5d,0x25,0xd3,0x7a,0xfc,0x95,0xb7,0x63,0xa4,0xb0,0xdd,0x12,0x9c,0x63,0x98,0xd5,0x6b,0x86,0x24,0xc0,0x30,0x9f,0xd1,0xa5,0x60,0xe4,0xfc,0x58,0x03,0x2f,0x7c,0xd1,0x8a,0x5e,0x09,0x2e,0x15,0x95,0xa1,0x07,0xc8,0x5f,0x9e,0x38,0x02,0x8f,0x36,0xa8,0x3b,0xe4,0x8d,0xcf,0x02,0x3b,0x43,0x90,0x43,0x26,0x41,0xc5,0x5d,0xfd,0xa1,0xaf,0x37,0x01,0x2f,0x03,0x3d,0xe8,0x8f,0x3e},
+    {0x94,0xa2,0x70,0x05,0xb9,0x15,0x8b,0x2f,0x49,0x45,0x08,0x67,0x70,0x42,0xf2,0x94,0x84,0xfd,0xbb,0x61,0xe1,0x5a,0x1c,0xde,0x07,0x40,0xac,0x7f,0x79,0x3b,0xba,0x75,0x3c,0xd1,0xef,0xe8,0x8d,0x4c,0x70,0x08,0x31,0x37,0xe0,0x33,0x8e,0x1a,0xc5,0xdf,0xe3,0xcd,0x60,0x12,0xa5,0x5d,0x9d,0xa5,0x86,0x8c,0x25,0xa6,0x99,0x08,0xd6,0x22,0x96,0xd1,0xcd,0x70,0xc0,0xdb,0x39,0x62,0x9a,0x8a,0x7d,0x6c,0x8b,0x8a,0xfe,0x60,0x60,0x12,0x40,0xeb,0xbc,0x47,0x88,0xb3,0x5e,0x9e,0x77,0x87,0x7b,0xd0,0x04,0x09},
+    {0x9c,0x91,0xba,0xdd,0xd4,0x1f,0xce,0xb4,0xaa,0x8d,0x4c,0xc7,0x3e,0xdb,0x31,0xcf,0x51,0xcc,0x86,0xad,0x63,0xcc,0x63,0x2c,0x07,0xde,0x1d,0xbc,0x3f,0x14,0xe2,0x43,0xb9,0x40,0xf9,0x48,0x66,0x2d,0x32,0xf4,0x39,0x0c,0x2d,0xbd,0x0c,0x2f,0x95,0x06,0x31,0xf9,0x81,0xa0,0xad,0x97,0x76,0x16,0x6c,0x2a,0xf7,0xba,0xce,0xaa,0x40,0x62,0xa0,0x95,0xa2,0x5b,0x9c,0x74,0x34,0xf8,0x5a,0xd2,0x37,0xca,0x5b,0x7c,0x94,0xd6,0x6a,0x31,0xc9,0xe7,0xa7,0x3b,0xf1,0x66,0xac,0x0c,0xb4,0x8d,0x23,0xaf,0xbd,0x56},
+    {0xeb,0x33,0x35,0xf5,0xe3,0xb9,0x2a,0x36,0x40,0x3d,0xb9,0x6e,0xd5,0x68,0x85,0x33,0x72,0x55,0x5a,0x1d,0x52,0x14,0x0e,0x9e,0x18,0x13,0x74,0x83,0x6d,0xa8,0x24,0x1d,0xb2,0x3b,0x9d,0xc1,0x6c,0xd3,0x10,0x13,0xb9,0x86,0x23,0x62,0xb7,0x6b,0x2a,0x06,0x5c,0x4f,0xa1,0xd7,0x91,0x85,0x9b,0x7c,0x54,0x57,0x1e,0x7e,0x50,0x31,0xaa,0x03,0x1f,0xce,0xd4,0xff,0x48,0x76,0xec,0xf4,0x1c,0x8c,0xac,0x54,0xf0,0xea,0x45,0xe0,0x7c,0x35,0x09,0x1d,0x82,0x25,0xd2,0x88,0x59,0x48,0xeb,0x9a,0xdc,0x61,0xb2,0x43},
+    {0xbb,0x79,0xbb,0x88,0x19,0x1e,0x5b,0xe5,0x9d,0x35,0x7a,0xc1,0x7d,0xd0,0x9e,0xa0,0x33,0xea,0x3d,0x60,0xe2,0x2e,0x2c,0xb0,0xc2,0x6b,0x27,0x5b,0xcf,0x55,0x60,0x32,0x64,0x13,0x95,0x6c,0x8b,0x3d,0x51,0x19,0x7b,0xf4,0x0b,0x00,0x26,0x71,0xfe,0x94,0x67,0x95,0x4f,0xd5,0xdd,0x10,0x8d,0x02,0x64,0x09,0x94,0x42,0xe2,0xd5,0xb4,0x02,0xf2,0x8d,0xd1,0x28,0xcb,0x55,0xa1,0xb4,0x08,0xe5,0x6c,0x18,0x46,0x46,0xcc,0xea,0x89,0x43,0x82,0x6c,0x93,0xf4,0x9c,0xc4,0x10,0x34,0x5d,0xae,0x09,0xc8,0xa6,0x27},
+    {0x88,0xb1,0x0d,0x1f,0xcd,0xeb,0xa6,0x8b,0xe8,0x5b,0x5a,0x67,0x3a,0xd7,0xd3,0x37,0x5a,0x58,0xf5,0x15,0xa3,0xdf,0x2e,0xf2,0x7e,0xa1,0x60,0xff,0x74,0x71,0xb6,0x2c,0x54,0x69,0x3d,0xc4,0x0a,0x27,0x2c,0xcd,0xb2,0xca,0x66,0x6a,0x57,0x3e,0x4a,0xdd,0x6c,0x03,0xd7,0x69,0x24,0x59,0xfa,0x79,0x99,0x25,0x8c,0x3d,0x60,0x03,0x15,0x22,0xd0,0xe1,0x0b,0x39,0xf9,0xcd,0xee,0x59,0xf1,0xe3,0x8c,0x72,0x44,0x20,0x42,0xa9,0xf4,0xf0,0x94,0x7a,0x66,0x1c,0x89,0x82,0x36,0xf4,0x90,0x38,0xb7,0xf4,0x1d,0x7b},
+    {0x24,0xa2,0xb2,0xb3,0xe0,0xf2,0x92,0xe4,0x60,0x11,0x55,0x2b,0x06,0x9e,0x6c,0x7c,0x0e,0x7b,0x7f,0x0d,0xe2,0x8f,0xeb,0x15,0x92,0x59,0xfc,0x58,0x26,0xef,0xfc,0x61,0x8c,0xf5,0xf8,0x07,0x18,0x22,0x2e,0x5f,0xd4,0x09,0x94,0xd4,0x9f,0x5c,0x55,0xe3,0x30,0xa6,0xb6,0x1f,0x8d,0xa8,0xaa,0xb2,0x3d,0xe0,0x52,0xd3,0x45,0x82,0x69,0x68,0x7a,0x18,0x18,0x2a,0x85,0x5d,0xb1,0xdb,0xd7,0xac,0xdd,0x86,0xd3,0xaa,0xe4,0xf3,0x82,0xc4,0xf6,0x0f,0x81,0xe2,0xba,0x44,0xcf,0x01,0xaf,0x3d,0x47,0x4c,0xcf,0x46},
+    {0xf9,0xe5,0xc4,0x9e,0xed,0x25,0x65,0x42,0x03,0x33,0x90,0x16,0x01,0xda,0x5e,0x0e,0xdc,0xca,0xe5,0xcb,0xf2,0xa7,0xb1,0x72,0x40,0x5f,0xeb,0x14,0xcd,0x7b,0x38,0x29,0x40,0x81,0x49,0xf1,0xa7,0x6e,0x3c,0x21,0x54,0x48,0x2b,0x39,0xf8,0x7e,0x1e,0x7c,0xba,0xce,0x29,0x56,0x8c,0xc3,0x88,0x24,0xbb,0xc5,0x8c,0x0d,0xe5,0xaa,0x65,0x10,0x57,0x0d,0x20,0xdf,0x25,0x45,0x2c,0x1c,0x4a,0x67,0xca,0xbf,0xd6,0x2d,0x3b,0x5c,0x30,0x40,0x83,0xe1,0xb1,0xe7,0x07,0x0a,0x16,0xe7,0x1c,0x4f,0xe6,0x98,0xa1,0x69},
+    {0xbc,0x78,0x1a,0xd9,0xe0,0xb2,0x62,0x90,0x67,0x96,0x50,0xc8,0x9c,0x88,0xc9,0x47,0xb8,0x70,0x50,0x40,0x66,0x4a,0xf5,0x9d,0xbf,0xa1,0x93,0x24,0xa9,0xe6,0x69,0x73,0xed,0xca,0xc5,0xdc,0x34,0x44,0x01,0xe1,0x33,0xfb,0x84,0x3c,0x96,0x5d,0xed,0x47,0xe7,0xa0,0x86,0xed,0x76,0x95,0x01,0x70,0xe4,0xf9,0x67,0xd2,0x7b,0x69,0xb2,0x25,0x64,0x68,0x98,0x13,0xfb,0x3f,0x67,0x9d,0xb8,0xc7,0x5d,0x41,0xd9,0xfb,0xa5,0x3c,0x5e,0x3b,0x27,0xdf,0x3b,0xcc,0x4e,0xe0,0xd2,0x4c,0x4e,0xb5,0x3d,0x68,0x20,0x14},
+    {0x97,0xd1,0x9d,0x24,0x1e,0xbd,0x78,0xb4,0x02,0xc1,0x58,0x5e,0x00,0x35,0x0c,0x62,0x5c,0xac,0xba,0xcc,0x2f,0xd3,0x02,0xfb,0x2d,0xa7,0x08,0xf5,0xeb,0x3b,0xb6,0x60,0xd0,0x5a,0xcc,0xc1,0x6f,0xbb,0xee,0x34,0x8b,0xac,0x46,0x96,0xe9,0x0c,0x1b,0x6a,0x53,0xde,0x6b,0xa6,0x49,0xda,0xb0,0xd3,0xc1,0x81,0xd0,0x61,0x41,0x3b,0xe8,0x31,0x4f,0x2b,0x06,0x9e,0x12,0xc7,0xe8,0x97,0xd8,0x0a,0x32,0x29,0x4f,0x8f,0xe4,0x49,0x3f,0x68,0x18,0x6f,0x4b,0xe1,0xec,0x5b,0x17,0x03,0x55,0x2d,0xb6,0x1e,0xcf,0x55},
+    {0x58,0x3d,0xc2,0x65,0x10,0x10,0x79,0x58,0x9c,0x81,0x94,0x50,0x6d,0x08,0x9d,0x8b,0xa7,0x5f,0xc5,0x12,0xa9,0x2f,0x40,0xe2,0xd4,0x91,0x08,0x57,0x64,0x65,0x9a,0x66,0x52,0x8c,0xf5,0x7d,0xe3,0xb5,0x76,0x30,0x36,0xcc,0x99,0xe7,0xdd,0xb9,0x3a,0xd7,0x20,0xee,0x13,0x49,0xe3,0x1c,0x83,0xbd,0x33,0x01,0xba,0x62,0xaa,0xfb,0x56,0x1a,0xec,0xc9,0x9d,0x5c,0x50,0x6b,0x3e,0x94,0x1a,0x37,0x7c,0xa7,0xbb,0x57,0x25,0x30,0x51,0x76,0x34,0x41,0x56,0xae,0x73,0x98,0x5c,0x8a,0xc5,0x99,0x67,0x83,0xc4,0x13},
+    {0xb9,0xe1,0xb3,0x5a,0x46,0x5d,0x3a,0x42,0x61,0x3f,0xf1,0xc7,0x87,0xc1,0x13,0xfc,0xb6,0xb9,0xb5,0xec,0x64,0x36,0xf8,0x19,0x07,0xb6,0x37,0xa6,0x93,0x0c,0xf8,0x66,0x80,0xd0,0x8b,0x5d,0x6a,0xfb,0xdc,0xc4,0x42,0x48,0x1a,0x57,0xec,0xc4,0xeb,0xde,0x65,0x53,0xe5,0xb8,0x83,0xe8,0xb2,0xd4,0x27,0xb8,0xe5,0xc8,0x7d,0xc8,0xbd,0x50,0x11,0xe1,0xdf,0x6e,0x83,0x37,0x6d,0x60,0xd9,0xab,0x11,0xf0,0x15,0x3e,0x35,0x32,0x96,0x3b,0xb7,0x25,0xc3,0x3a,0xb0,0x64,0xae,0xd5,0x5f,0x72,0x44,0x64,0xd5,0x1d},
+    {0x7d,0x12,0x62,0x33,0xf8,0x7f,0xa4,0x8f,0x15,0x7c,0xcd,0x71,0xc4,0x6a,0x9f,0xbc,0x8b,0x0c,0x22,0x49,0x43,0x45,0x71,0x6e,0x2e,0x73,0x9f,0x21,0x12,0x59,0x64,0x0e,0x9a,0xc8,0xba,0x08,0x00,0xe6,0x97,0xc2,0xe0,0xc3,0xe1,0xea,0x11,0xea,0x4c,0x7d,0x7c,0x97,0xe7,0x9f,0xe1,0x8b,0xe3,0xf3,0xcd,0x05,0xa3,0x63,0x0f,0x45,0x3a,0x3a,0x27,0x46,0x39,0xd8,0x31,0x2f,0x8f,0x07,0x10,0xa5,0x94,0xde,0x83,0x31,0x9d,0x38,0x80,0x6f,0x99,0x17,0x6d,0x6c,0xe3,0xd1,0x7b,0xa8,0xa9,0x93,0x93,0x8d,0x8c,0x31},
+    {0x19,0xfe,0xff,0x2a,0x03,0x5d,0x74,0xf2,0x66,0xdb,0x24,0x7f,0x49,0x3c,0x9f,0x0c,0xef,0x98,0x85,0xba,0xe3,0xd3,0x98,0xbc,0x14,0x53,0x1d,0x9a,0x67,0x7c,0x4c,0x22,0x98,0xd3,0x1d,0xab,0x29,0x9e,0x66,0x5d,0x3b,0x9e,0x2d,0x34,0x58,0x16,0x92,0xfc,0xcd,0x73,0x59,0xf3,0xfd,0x1d,0x85,0x55,0xf6,0x0a,0x95,0x25,0xc3,0x41,0x9a,0x50,0xe9,0x25,0xf9,0xa6,0xdc,0x6e,0xc0,0xbd,0x33,0x1f,0x1b,0x64,0xf4,0xf3,0x3e,0x79,0x89,0x3e,0x83,0x9d,0x80,0x12,0xec,0x82,0x89,0x13,0xa1,0x28,0x23,0xf0,0xbf,0x05},
+    {0x0b,0xe0,0xca,0x23,0x70,0x13,0x32,0x36,0x59,0xcf,0xac,0xd1,0x0a,0xcf,0x4a,0x54,0x88,0x1c,0x1a,0xd2,0x49,0x10,0x74,0x96,0xa7,0x44,0x2a,0xfa,0xc3,0x8c,0x0b,0x78,0xe4,0x12,0xc5,0x0d,0xdd,0xa0,0x81,0x68,0xfe,0xfa,0xa5,0x44,0xc8,0x0d,0xe7,0x4f,0x40,0x52,0x4a,0x8f,0x6b,0x8e,0x74,0x1f,0xea,0xa3,0x01,0xee,0xcd,0x77,0x62,0x57,0x5f,0x30,0x4f,0x23,0xbc,0x8a,0xf3,0x1e,0x08,0xde,0x05,0x14,0xbd,0x7f,0x57,0x9a,0x0d,0x2a,0xe6,0x34,0x14,0xa5,0x82,0x5e,0xa1,0xb7,0x71,0x62,0x72,0x18,0xf4,0x5f},
+    {0x9d,0xdb,0x89,0x17,0x0c,0x08,0x8e,0x39,0xf5,0x78,0xe7,0xf3,0x25,0x20,0x60,0xa7,0x5d,0x03,0xbd,0x06,0x4c,0x89,0x98,0xfa,0xbe,0x66,0xa9,0x25,0xdc,0x03,0x6a,0x10,0x40,0x95,0xb6,0x13,0xe8,0x47,0xdb,0xe5,0xe1,0x10,0x26,0x43,0x3b,0x2a,0x5d,0xf3,0x76,0x12,0x78,0x38,0xe9,0x26,0x1f,0xac,0x69,0xcb,0xa0,0xa0,0x8c,0xdb,0xd4,0x29,0xd0,0x53,0x33,0x33,0xaf,0x0a,0xad,0xd9,0xe5,0x09,0xd3,0xac,0xa5,0x9d,0x66,0x38,0xf0,0xf7,0x88,0xc8,0x8a,0x65,0x57,0x3c,0xfa,0xbe,0x2c,0x05,0x51,0x8a,0xb3,0x4a},
+    {0x93,0xd5,0x68,0x67,0x25,0x2b,0x7c,0xda,0x13,0xca,0x22,0x44,0x57,0xc0,0xc1,0x98,0x1d,0xce,0x0a,0xca,0xd5,0x0b,0xa8,0xf1,0x90,0xa6,0x88,0xc0,0xad,0xd1,0xcd,0x29,0x9c,0xc0,0xdd,0x5f,0xef,0xd1,0xcf,0xd6,0xce,0x5d,0x57,0xf7,0xfd,0x3e,0x2b,0xe8,0xc2,0x34,0x16,0x20,0x5d,0x6b,0xd5,0x25,0x9b,0x2b,0xed,0x04,0xbb,0xc6,0x41,0x30,0x48,0xe1,0x56,0xd9,0xf9,0xf2,0xf2,0x0f,0x2e,0x6b,0x35,0x9f,0x75,0x97,0xe7,0xad,0x5c,0x02,0x6c,0x5f,0xbb,0x98,0x46,0x1a,0x7b,0x9a,0x04,0x14,0x68,0xbd,0x4b,0x10},
+    {0x67,0xed,0xf1,0x68,0x31,0xfd,0xf0,0x51,0xc2,0x3b,0x6f,0xd8,0xcd,0x1d,0x81,0x2c,0xde,0xf2,0xd2,0x04,0x43,0x5c,0xdc,0x44,0x49,0x71,0x2a,0x09,0x57,0xcc,0xe8,0x5b,0x63,0xf1,0x7f,0xd6,0x5f,0x9a,0x5d,0xa9,0x81,0x56,0xc7,0x4c,0x9d,0xe6,0x2b,0xe9,0x57,0xf2,0x20,0xde,0x4c,0x02,0xf8,0xb7,0xf5,0x2d,0x07,0xfb,0x20,0x2a,0x4f,0x20,0x79,0xb0,0xeb,0x30,0x3d,0x3b,0x14,0xc8,0x30,0x2e,0x65,0xbd,0x5a,0x15,0x89,0x75,0x31,0x5c,0x6d,0x8f,0x31,0x3c,0x3c,0x65,0x1f,0x16,0x79,0xc2,0x17,0xfb,0x70,0x25},
+    {0x75,0x15,0xb6,0x2c,0x7f,0x36,0xfa,0x3e,0x6c,0x02,0xd6,0x1c,0x76,0x6f,0xf9,0xf5,0x62,0x25,0xb5,0x65,0x2a,0x14,0xc7,0xe8,0xcd,0x0a,0x03,0x53,0xea,0x65,0xcb,0x3d,0x5a,0x24,0xb8,0x0b,0x55,0xa9,0x2e,0x19,0xd1,0x50,0x90,0x8f,0xa8,0xfb,0xe6,0xc8,0x35,0xc9,0xa4,0x88,0x2d,0xea,0x86,0x79,0x68,0x86,0x01,0xde,0x91,0x5f,0x1c,0x24,0xaa,0x6c,0xde,0x40,0x29,0x17,0xd8,0x28,0x3a,0x73,0xd9,0x22,0xf0,0x2c,0xbf,0x8f,0xd1,0x01,0x5b,0x23,0xdd,0xfc,0xd7,0x16,0xe5,0xf0,0xcd,0x5f,0xdd,0x0e,0x42,0x08},
+    {0x4a,0xfa,0x62,0x83,0xab,0x20,0xff,0xcd,0x6e,0x3e,0x1a,0xe2,0xd4,0x18,0xe1,0x57,0x2b,0xe6,0x39,0xfc,0x17,0x96,0x17,0xe3,0xfd,0x69,0x17,0xbc,0xef,0x53,0x9a,0x0d,0xce,0x10,0xf4,0x04,0x4e,0xc3,0x58,0x03,0x85,0x06,0x6e,0x27,0x5a,0x5b,0x13,0xb6,0x21,0x15,0xb9,0xeb,0xc7,0x70,0x96,0x5d,0x9c,0x88,0xdb,0x21,0xf3,0x54,0xd6,0x04,0xd5,0xb5,0xbd,0xdd,0x16,0xc1,0x7d,0x5e,0x2d,0xdd,0xa5,0x8d,0xb6,0xde,0x54,0x29,0x92,0xa2,0x34,0x33,0x17,0x08,0xb6,0x1c,0xd7,0x1a,0x99,0x18,0x26,0x4f,0x7a,0x4a},
+    {0x95,0x5f,0xb1,0x5f,0x02,0x18,0xa7,0xf4,0x8f,0x1b,0x5c,0x6b,0x34,0x5f,0xf6,0x3d,0x12,0x11,0xe0,0x00,0x85,0xf0,0xfc,0xcd,0x48,0x18,0xd3,0xdd,0x4c,0x0c,0xb5,0x11,0x4b,0x2a,0x37,0xaf,0x91,0xb2,0xc3,0x24,0xf2,0x47,0x81,0x71,0x70,0x82,0xda,0x93,0xf2,0x9e,0x89,0x86,0x64,0x85,0x84,0xdd,0x33,0xee,0xe0,0x23,0x42,0x31,0x96,0x4a,0xd6,0xff,0xa4,0x08,0x44,0x27,0xe8,0xa6,0xd9,0x76,0x15,0x9c,0x7e,0x17,0x8e,0x73,0xf2,0xb3,0x02,0x3d,0xb6,0x48,0x33,0x77,0x51,0xcc,0x6b,0xce,0x4d,0xce,0x4b,0x4f},
+    {0x84,0x25,0x24,0xe2,0x5a,0xce,0x1f,0xa7,0x9e,0x8a,0xf5,0x92,0x56,0x72,0xea,0x26,0xf4,0x3c,0xea,0x1c,0xd7,0x09,0x1a,0xd2,0xe6,0x01,0x1c,0xb7,0x14,0xdd,0xfc,0x73,0x6f,0x0b,0x9d,0xc4,0x6e,0x61,0xe2,0x30,0x17,0x23,0xec,0xca,0x8f,0x71,0x56,0xe4,0xa6,0x4f,0x6b,0xf2,0x9b,0x40,0xeb,0x48,0x37,0x5f,0x59,0x61,0xe5,0xce,0x42,0x30,0x41,0xac,0x9b,0x44,0x79,0x70,0x7e,0x42,0x0a,0x31,0xe2,0xbc,0x6d,0xe3,0x5a,0x85,0x7c,0x1a,0x84,0x5f,0x21,0x76,0xae,0x4c,0xd6,0xe1,0x9c,0x9a,0x0c,0x74,0x9e,0x38},
+    {0xce,0xb9,0xdc,0x34,0xae,0xb3,0xfc,0x64,0xad,0xd0,0x48,0xe3,0x23,0x03,0x50,0x97,0x1b,0x38,0xc6,0x62,0x7d,0xf0,0xb3,0x45,0x88,0x67,0x5a,0x46,0x79,0x53,0x54,0x61,0x28,0xac,0x0e,0x57,0xf6,0x78,0xbd,0xc9,0xe1,0x9c,0x91,0x27,0x32,0x0b,0x5b,0xe5,0xed,0x91,0x9b,0xa1,0xab,0x3e,0xfc,0x65,0x90,0x36,0x26,0xd6,0xe5,0x25,0xc4,0x25,0x6e,0xde,0xd7,0xf1,0xa6,0x06,0x3e,0x3f,0x08,0x23,0x06,0x8e,0x27,0x76,0xf9,0x3e,0x77,0x6c,0x8a,0x4e,0x26,0xf6,0x14,0x8c,0x59,0x47,0x48,0x15,0x89,0xa0,0x39,0x65},
+    {0x73,0xf7,0xd2,0xc3,0x74,0x1f,0xd2,0xe9,0x45,0x68,0xc4,0x25,0x41,0x54,0x50,0xc1,0x33,0x9e,0xb9,0xf9,0xe8,0x5c,0x4e,0x62,0x6c,0x18,0xcd,0xc5,0xaa,0xe4,0xc5,0x11,0x19,0x4a,0xbb,0x14,0xd4,0xdb,0xc4,0xdd,0x8e,0x4f,0x42,0x98,0x3c,0xbc,0xb2,0x19,0x69,0x71,0xca,0x36,0xd7,0x9f,0xa8,0x48,0x90,0xbd,0x19,0xf0,0x0e,0x32,0x65,0x0f,0xc6,0xe0,0xfd,0xca,0xb1,0xd1,0x86,0xd4,0x81,0x51,0x3b,0x16,0xe3,0xe6,0x3f,0x4f,0x9a,0x93,0xf2,0xfa,0x0d,0xaf,0xa8,0x59,0x2a,0x07,0x33,0xec,0xbd,0xc7,0xab,0x4c},
+    {0x2e,0x0a,0x9c,0x08,0x24,0x96,0x9e,0x23,0x38,0x47,0xfe,0x3a,0xc0,0xc4,0x48,0xc7,0x2a,0xa1,0x4f,0x76,0x2a,0xed,0xdb,0x17,0x82,0x85,0x1c,0x32,0xf0,0x93,0x9b,0x63,0x89,0xd2,0x78,0x3f,0x8f,0x78,0x8f,0xc0,0x9f,0x4d,0x40,0xa1,0x2c,0xa7,0x30,0xfe,0x9d,0xcc,0x65,0xcf,0xfc,0x8b,0x77,0xf2,0x21,0x20,0xcb,0x5a,0x16,0x98,0xe4,0x7e,0xc3,0xa1,0x11,0x91,0xe3,0x08,0xd5,0x7b,0x89,0x74,0x90,0x80,0xd4,0x90,0x2b,0x2b,0x19,0xfd,0x72,0xae,0xc2,0xae,0xd2,0xe7,0xa6,0x02,0xb6,0x85,0x3c,0x49,0xdf,0x0e},
+    {0x68,0x5a,0x9b,0x59,0x58,0x81,0xcc,0xae,0x0e,0xe2,0xad,0xeb,0x0f,0x4f,0x57,0xea,0x07,0x7f,0xb6,0x22,0x74,0x1d,0xe4,0x4f,0xb4,0x4f,0x9d,0x01,0xe3,0x92,0x3b,0x40,0x13,0x41,0x76,0x84,0xd2,0xc4,0x67,0x67,0x35,0xf8,0xf5,0xf7,0x3f,0x40,0x90,0xa0,0xde,0xbe,0xe6,0xca,0xfa,0xcf,0x8f,0x1c,0x69,0xa3,0xdf,0xd1,0x54,0x0c,0xc0,0x04,0xf8,0x5c,0x46,0x8b,0x81,0x2f,0xc2,0x4d,0xf8,0xef,0x80,0x14,0x5a,0xf3,0xa0,0x71,0x57,0xd6,0xc7,0x04,0xad,0xbf,0xe8,0xae,0xf4,0x76,0x61,0xb2,0x2a,0xb1,0x5b,0x35},
+    {0xf4,0xbb,0x93,0x74,0xcc,0x64,0x1e,0xa7,0xc3,0xb0,0xa3,0xec,0xd9,0x84,0xbd,0xe5,0x85,0xe7,0x05,0xfa,0x0c,0xc5,0x6b,0x0a,0x12,0xc3,0x2e,0x18,0x32,0x81,0x9b,0x0f,0x18,0x73,0x8c,0x5a,0xc7,0xda,0x01,0xa3,0x11,0xaa,0xce,0xb3,0x9d,0x03,0x90,0xed,0x2d,0x3f,0xae,0x3b,0xbf,0x7c,0x07,0x6f,0x8e,0xad,0x52,0xe0,0xf8,0xea,0x18,0x75,0x32,0x6c,0x7f,0x1b,0xc4,0x59,0x88,0xa4,0x98,0x32,0x38,0xf4,0xbc,0x60,0x2d,0x0f,0xd9,0xd1,0xb1,0xc9,0x29,0xa9,0x15,0x18,0xc4,0x55,0x17,0xbb,0x1b,0x87,0xc3,0x47},
+    {0x48,0x4f,0xec,0x71,0x97,0x53,0x44,0x51,0x6e,0x5d,0x8c,0xc9,0x7d,0xb1,0x05,0xf8,0x6b,0xc6,0xc3,0x47,0x1a,0xc1,0x62,0xf7,0xdc,0x99,0x46,0x76,0x85,0x9b,0xb8,0x00,0xb0,0x66,0x50,0xc8,0x50,0x5d,0xe6,0xfb,0xb0,0x99,0xa2,0xb3,0xb0,0xc4,0xec,0x62,0xe0,0xe8,0x1a,0x44,0xea,0x54,0x37,0xe5,0x5f,0x8d,0xd4,0xe8,0x2c,0xa0,0xfe,0x08,0xd0,0xea,0xde,0x68,0x76,0xdd,0x4d,0x82,0x23,0x5d,0x68,0x4b,0x20,0x45,0x64,0xc8,0x65,0xd6,0x89,0x5d,0xcd,0xcf,0x14,0xb5,0x37,0xd5,0x75,0x4f,0xa7,0x29,0x38,0x47},
+    {0x18,0xc4,0x79,0x46,0x75,0xda,0xd2,0x82,0xf0,0x8d,0x61,0xb2,0xd8,0xd7,0x3b,0xe6,0x0a,0xeb,0x47,0xac,0x24,0xef,0x5e,0x35,0xb4,0xc6,0x33,0x48,0x4c,0x68,0x78,0x20,0xc9,0x02,0x39,0xad,0x3a,0x53,0xd9,0x23,0x8f,0x58,0x03,0xef,0xce,0xdd,0xc2,0x64,0xb4,0x2f,0xe1,0xcf,0x90,0x73,0x25,0x15,0x90,0xd3,0xe4,0x44,0x4d,0x8b,0x66,0x6c,0x0c,0x82,0x78,0x7a,0x21,0xcf,0x48,0x3b,0x97,0x3e,0x27,0x81,0xb2,0x0a,0x6a,0xf7,0x7b,0xed,0x8e,0x8c,0xa7,0x65,0x6c,0xa9,0x3f,0x43,0x8a,0x4f,0x05,0xa6,0x11,0x74},
+    {0x6d,0xc8,0x9d,0xb9,0x32,0x9d,0x65,0x4d,0x15,0xf1,0x3a,0x60,0x75,0xdc,0x4c,0x04,0x88,0xe4,0xc2,0xdc,0x2c,0x71,0x4c,0xb3,0xff,0x34,0x81,0xfb,0x74,0x65,0x13,0x7c,0xb4,0x75,0xb1,0x18,0x3d,0xe5,0x9a,0x57,0x02,0xa1,0x92,0xf3,0x59,0x31,0x71,0x68,0xf5,0x35,0xef,0x1e,0xba,0xec,0x55,0x84,0x8f,0x39,0x8c,0x45,0x72,0xa8,0xc9,0x1e,0x9b,0x50,0xa2,0x00,0xd4,0xa4,0xe6,0xb8,0xb4,0x82,0xc8,0x0b,0x02,0xd7,0x81,0x9b,0x61,0x75,0x95,0xf1,0x9b,0xcc,0xe7,0x57,0x60,0x64,0xcd,0xc7,0xa5,0x88,0xdd,0x3a},
+    {0xf2,0xdc,0x35,0xb6,0x70,0x57,0x89,0xab,0xbc,0x1f,0x6c,0xf6,0x6c,0xef,0xdf,0x02,0x87,0xd1,0xb6,0xbe,0x68,0x02,0x53,0x85,0x74,0x9e,0x87,0xcc,0xfc,0x29,0x99,0x24,0x46,0x30,0x39,0x59,0xd4,0x98,0xc2,0x85,0xec,0x59,0xf6,0x5f,0x98,0x35,0x7e,0x8f,0x3a,0x6e,0xf6,0xf2,0x2a,0xa2,0x2c,0x1d,0x20,0xa7,0x06,0xa4,0x31,0x11,0xba,0x61,0x29,0x90,0x95,0x16,0xf1,0xa0,0xd0,0xa3,0x89,0xbd,0x7e,0xba,0x6c,0x6b,0x3b,0x02,0x07,0x33,0x78,0x26,0x3e,0x5a,0xf1,0x7b,0xe7,0xec,0xd8,0xbb,0x0c,0x31,0x20,0x56},
+    {0x43,0xd6,0x34,0x49,0x43,0x93,0x89,0x52,0xf5,0x22,0x12,0xa5,0x06,0xf8,0xdb,0xb9,0x22,0x1c,0xf4,0xc3,0x8f,0x87,0x6d,0x8f,0x30,0x97,0x9d,0x4d,0x2a,0x6a,0x67,0x37,0xd6,0x85,0xe2,0x77,0xf4,0xb5,0x46,0x66,0x93,0x61,0x8f,0x6c,0x67,0xff,0xe8,0x40,0xdd,0x94,0xb5,0xab,0x11,0x73,0xec,0xa6,0x4d,0xec,0x8c,0x65,0xf3,0x46,0xc8,0x7e,0xc7,0x2e,0xa2,0x1d,0x3f,0x8f,0x5e,0x9b,0x13,0xcd,0x01,0x6c,0x77,0x1d,0x0f,0x13,0xb8,0x9f,0x98,0xa2,0xcf,0x8f,0x4c,0x21,0xd5,0x9d,0x9b,0x39,0x23,0xf7,0xaa,0x6d},
+    {0x47,0xbe,0x3d,0xeb,0x62,0x75,0x3a,0x5f,0xb8,0xa0,0xbd,0x8e,0x54,0x38,0xea,0xf7,0x99,0x72,0x74,0x45,0x31,0xe5,0xc3,0x00,0x51,0xd5,0x27,0x16,0xe7,0xe9,0x04,0x13,0xa2,0x8e,0xad,0xac,0xbf,0x04,0x3b,0x58,0x84,0xe8,0x8b,0x14,0xe8,0x43,0xb7,0x29,0xdb,0xc5,0x10,0x08,0x3b,0x58,0x1e,0x2b,0xaa,0xbb,0xb3,0x8e,0xe5,0x49,0x54,0x2b,0xfe,0x9c,0xdc,0x6a,0xd2,0x14,0x98,0x78,0x0b,0xdd,0x48,0x8b,0x3f,0xab,0x1b,0x3c,0x0a,0xc6,0x79,0xf9,0xff,0xe1,0x0f,0xda,0x93,0xd6,0x2d,0x7c,0x2d,0xde,0x68,0x44},
+    {0x9e,0x46,0x19,0x94,0x5e,0x35,0xbb,0x51,0x54,0xc7,0xdd,0x23,0x4c,0xdc,0xe6,0x33,0x62,0x99,0x7f,0x44,0xd6,0xb6,0xa5,0x93,0x63,0xbd,0x44,0xfb,0x6f,0x7c,0xce,0x6c,0xce,0x07,0x63,0xf8,0xc6,0xd8,0x9a,0x4b,0x28,0x0c,0x5d,0x43,0x31,0x35,0x11,0x21,0x2c,0x77,0x7a,0x65,0xc5,0x66,0xa8,0xd4,0x52,0x73,0x24,0x63,0x7e,0x42,0xa6,0x5d,0xca,0x22,0xac,0xde,0x88,0xc6,0x94,0x1a,0xf8,0x1f,0xae,0xbb,0xf7,0x6e,0x06,0xb9,0x0f,0x58,0x59,0x8d,0x38,0x8c,0xad,0x88,0xa8,0x2c,0x9f,0xe7,0xbf,0x9a,0xf2,0x58},
+    {0x68,0x3e,0xe7,0x8d,0xab,0xcf,0x0e,0xe9,0xa5,0x76,0x7e,0x37,0x9f,0x6f,0x03,0x54,0x82,0x59,0x01,0xbe,0x0b,0x5b,0x49,0xf0,0x36,0x1e,0xf4,0xa7,0xc4,0x29,0x76,0x57,0xf6,0xcd,0x0e,0x71,0xbf,0x64,0x5a,0x4b,0x3c,0x29,0x2c,0x46,0x38,0xe5,0x4c,0xb1,0xb9,0x3a,0x0b,0xd5,0x56,0xd0,0x43,0x36,0x70,0x48,0x5b,0x18,0x24,0x37,0xf9,0x6a,0x88,0xa8,0xc6,0x09,0x45,0x02,0x20,0x32,0x73,0x89,0x55,0x4b,0x13,0x36,0xe0,0xd2,0x9f,0x28,0x33,0x3c,0x23,0x36,0xe2,0x83,0x8f,0xc1,0xae,0x0c,0xbb,0x25,0x1f,0x70},
+    {0xed,0x6c,0x61,0xe4,0xf8,0xb0,0xa8,0xc3,0x7d,0xa8,0x25,0x9e,0x0e,0x66,0x00,0xf7,0x9c,0xa5,0xbc,0xf4,0x1f,0x06,0xe3,0x61,0xe9,0x0b,0xc4,0xbd,0xbf,0x92,0x0c,0x2e,0x13,0xc1,0xbe,0x7c,0xd9,0xf6,0x18,0x9d,0xe4,0xdb,0xbf,0x74,0xe6,0x06,0x4a,0x84,0xd6,0x60,0x4e,0xac,0x22,0xb5,0xf5,0x20,0x51,0x5e,0x95,0x50,0xc0,0x5b,0x0a,0x72,0x35,0x5a,0x80,0x9b,0x43,0x09,0x3f,0x0c,0xfc,0xab,0x42,0x62,0x37,0x8b,0x4e,0xe8,0x46,0x93,0x22,0x5c,0xf3,0x17,0x14,0x69,0xec,0xf0,0x4e,0x14,0xbb,0x9c,0x9b,0x0e},
+    {0xad,0x20,0x57,0xfb,0x8f,0xd4,0xba,0xfb,0x0e,0x0d,0xf9,0xdb,0x6b,0x91,0x81,0xee,0xbf,0x43,0x55,0x63,0x52,0x31,0x81,0xd4,0xd8,0x7b,0x33,0x3f,0xeb,0x04,0x11,0x22,0xee,0xbe,0xb1,0x5d,0xd5,0x9b,0xee,0x8d,0xb9,0x3f,0x72,0x0a,0x37,0xab,0xc3,0xc9,0x91,0xd7,0x68,0x1c,0xbf,0xf1,0xa8,0x44,0xde,0x3c,0xfd,0x1c,0x19,0x44,0x6d,0x36,0x14,0x8c,0xbc,0xf2,0x43,0x17,0x3c,0x9e,0x3b,0x6c,0x85,0xb5,0xfc,0x26,0xda,0x2e,0x97,0xfb,0xa7,0x68,0x0e,0x2f,0xb8,0xcc,0x44,0x32,0x59,0xbc,0xe6,0xa4,0x67,0x41},
+    {0x00,0x27,0xf6,0x76,0x28,0x9d,0x3b,0x64,0xeb,0x68,0x76,0x0e,0x40,0x9d,0x1d,0x5d,0x84,0x06,0xfc,0x21,0x03,0x43,0x4b,0x1b,0x6a,0x24,0x55,0x22,0x7e,0xbb,0x38,0x79,0xee,0x8f,0xce,0xf8,0x65,0x26,0xbe,0xc2,0x2c,0xd6,0x80,0xe8,0x14,0xff,0x67,0xe9,0xee,0x4e,0x36,0x2f,0x7e,0x6e,0x2e,0xf1,0xf6,0xd2,0x7e,0xcb,0x70,0x33,0xb3,0x34,0xcc,0xd6,0x81,0x86,0xee,0x91,0xc5,0xcd,0x53,0xa7,0x85,0xed,0x9c,0x10,0x02,0xce,0x83,0x88,0x80,0x58,0xc1,0x85,0x74,0xed,0xe4,0x65,0xfe,0x2d,0x6e,0xfc,0x76,0x11},
+    {0x9b,0x61,0x9c,0x5b,0xd0,0x6c,0xaf,0xb4,0x80,0x84,0xa5,0xb2,0xf4,0xc9,0xdf,0x2d,0xc4,0x4d,0xe9,0xeb,0x02,0xa5,0x4f,0x3d,0x34,0x5f,0x7d,0x67,0x4c,0x3a,0xfc,0x08,0xb8,0x0e,0x77,0x49,0x89,0xe2,0x90,0xdb,0xa3,0x40,0xf4,0xac,0x2a,0xcc,0xfb,0x98,0x9b,0x87,0xd7,0xde,0xfe,0x4f,0x35,0x21,0xb6,0x06,0x69,0xf2,0x54,0x3e,0x6a,0x1f,0xea,0x34,0x07,0xd3,0x99,0xc1,0xa4,0x60,0xd6,0x5c,0x16,0x31,0xb6,0x85,0xc0,0x40,0x95,0x82,0x59,0xf7,0x23,0x3e,0x33,0xe2,0xd1,0x00,0xb9,0x16,0x01,0xad,0x2f,0x4f},
+    {0x54,0x4e,0xae,0x94,0x41,0xb2,0xbe,0x44,0x6c,0xef,0x57,0x18,0x51,0x1c,0x54,0x5f,0x98,0x04,0x8d,0x36,0x2d,0x6b,0x1e,0xa6,0xab,0xf7,0x2e,0x97,0xa4,0x84,0x54,0x44,0x38,0xb6,0x3b,0xb7,0x1d,0xd9,0x2c,0x96,0x08,0x9c,0x12,0xfc,0xaa,0x77,0x05,0xe6,0x89,0x16,0xb6,0xf3,0x39,0x9b,0x61,0x6f,0x81,0xee,0x44,0x29,0x5f,0x99,0x51,0x34,0x7c,0x7d,0xea,0x9f,0xd0,0xfc,0x52,0x91,0xf6,0x5c,0x93,0xb0,0x94,0x6c,0x81,0x4a,0x40,0x5c,0x28,0x47,0xaa,0x9a,0x8e,0x25,0xb7,0x93,0x28,0x04,0xa6,0x9c,0xb8,0x10},
+    {0x9c,0x28,0x18,0x97,0x49,0x47,0x59,0x3d,0x26,0x3f,0x53,0x24,0xc5,0xf8,0xeb,0x12,0x15,0xef,0xc3,0x14,0xcb,0xbf,0x62,0x02,0x8e,0x51,0xb7,0x77,0xd5,0x78,0xb8,0x20,0x6e,0xf0,0x45,0x5a,0xbe,0x41,0x39,0x75,0x65,0x5f,0x9c,0x6d,0xed,0xae,0x7c,0xd0,0xb6,0x51,0xff,0x72,0x9c,0x6b,0x77,0x11,0xa9,0x4d,0x0d,0xef,0xd9,0xd1,0xd2,0x17,0x6a,0x3e,0x3f,0x07,0x18,0xaf,0xf2,0x27,0x69,0x10,0x52,0xd7,0x19,0xe5,0x3f,0xfd,0x22,0x00,0xa6,0x3c,0x2c,0xb7,0xe3,0x22,0xa7,0xc6,0x65,0xcc,0x63,0x4f,0x21,0x72},
+    {0x93,0xa6,0x07,0x53,0x40,0x7f,0xe3,0xb4,0x95,0x67,0x33,0x2f,0xd7,0x14,0xa7,0xab,0x99,0x10,0x76,0x73,0xa7,0xd0,0xfb,0xd6,0xc9,0xcb,0x71,0x81,0xc5,0x48,0xdf,0x5f,0xc9,0x29,0x3b,0xf4,0xb9,0xb7,0x9d,0x1d,0x75,0x8f,0x51,0x4f,0x4a,0x82,0x05,0xd6,0xc4,0x9d,0x2f,0x31,0xbd,0x72,0xc0,0xf2,0xb0,0x45,0x15,0x5a,0x85,0xac,0x24,0x1f,0xaa,0x05,0x95,0x8e,0x32,0x08,0xd6,0x24,0xee,0x20,0x14,0x0c,0xd1,0xc1,0x48,0x47,0xa2,0x25,0xfb,0x06,0x5c,0xe4,0xff,0xc7,0xe6,0x95,0xe3,0x2a,0x9e,0x73,0xba,0x00},
+    {0xd6,0x90,0x87,0x5c,0xde,0x98,0x2e,0x59,0xdf,0xa2,0xc2,0x45,0xd3,0xb7,0xbf,0xe5,0x22,0x99,0xb4,0xf9,0x60,0x3b,0x5a,0x11,0xf3,0x78,0xad,0x67,0x3e,0x3a,0x28,0x03,0x26,0xbb,0x88,0xea,0xf5,0x26,0x44,0xae,0xfb,0x3b,0x97,0x84,0xd9,0x79,0x06,0x36,0x50,0x4e,0x69,0x26,0x0c,0x03,0x9f,0x5c,0x26,0xd2,0x18,0xd5,0xe7,0x7d,0x29,0x72,0x39,0xb9,0x0c,0xbe,0xc7,0x1d,0x24,0x48,0x80,0x30,0x63,0x8b,0x4d,0x9b,0xf1,0x32,0x08,0x93,0x28,0x02,0x0d,0xc9,0xdf,0xd3,0x45,0x19,0x27,0x46,0x68,0x29,0xe1,0x05},
+    {0x5a,0x49,0x9c,0x2d,0xb3,0xee,0x82,0xba,0x7c,0xb9,0x2b,0xf1,0xfc,0xc8,0xef,0xce,0xe0,0xd1,0xb5,0x93,0xae,0xab,0x2d,0xb0,0x9b,0x8d,0x69,0x13,0x9c,0x0c,0xc0,0x39,0x50,0x45,0x2c,0x24,0xc8,0xbb,0xbf,0xad,0xd9,0x81,0x30,0xd0,0xec,0x0c,0xc8,0xbc,0x92,0xdf,0xc8,0xf5,0xa6,0x66,0x35,0x84,0x4c,0xce,0x58,0x82,0xd3,0x25,0xcf,0x78,0x68,0x9d,0x48,0x31,0x8e,0x6b,0xae,0x15,0x87,0xf0,0x2b,0x9c,0xab,0x1c,0x85,0xaa,0x05,0xfa,0x4e,0xf0,0x97,0x5a,0xa7,0xc9,0x32,0xf8,0x3f,0x6b,0x07,0x52,0x6b,0x00},
+    {0x1c,0x78,0x95,0x9d,0xe1,0xcf,0xe0,0x29,0xe2,0x10,0x63,0x96,0x18,0xdf,0x81,0xb6,0x39,0x6b,0x51,0x70,0xd3,0x39,0xdf,0x57,0x22,0x61,0xc7,0x3b,0x44,0xe3,0x57,0x4d,0x2d,0x08,0xce,0xb9,0x16,0x7e,0xcb,0xf5,0x29,0xbc,0x7a,0x41,0x4c,0xf1,0x07,0x34,0xab,0xa7,0xf4,0x2b,0xce,0x6b,0xb3,0xd4,0xce,0x75,0x9f,0x1a,0x56,0xe9,0xe2,0x7d,0xcb,0x5e,0xa5,0xb6,0xf4,0xd4,0x70,0xde,0x99,0xdb,0x85,0x5d,0x7f,0x52,0x01,0x48,0x81,0x9a,0xee,0xd3,0x40,0xc4,0xc9,0xdb,0xed,0x29,0x60,0x1a,0xaf,0x90,0x2a,0x6b},
+    {0x97,0x1e,0xe6,0x9a,0xfc,0xf4,0x23,0x69,0xd1,0x5f,0x3f,0xe0,0x1d,0x28,0x35,0x57,0x2d,0xd1,0xed,0xe6,0x43,0xae,0x64,0xa7,0x4a,0x3e,0x2d,0xd1,0xe9,0xf4,0xd8,0x5f,0x0a,0xd8,0xb2,0x5b,0x24,0xf3,0xeb,0x77,0x9b,0x07,0xb9,0x2f,0x47,0x1b,0x30,0xd8,0x33,0x73,0xee,0x4c,0xf2,0xe6,0x47,0xc6,0x09,0x21,0x6c,0x27,0xc8,0x12,0x58,0x46,0xd9,0x62,0x10,0x2a,0xb2,0xbe,0x43,0x4d,0x16,0xdc,0x31,0x38,0x75,0xfb,0x65,0x70,0xd7,0x68,0x29,0xde,0x7b,0x4a,0x0d,0x18,0x90,0x67,0xb1,0x1c,0x2b,0x2c,0xb3,0x05},
+    {0xfd,0xa8,0x4d,0xd2,0xcc,0x5e,0xc0,0xc8,0x83,0xef,0xdf,0x05,0xac,0x1a,0xcf,0xa1,0x61,0xcd,0xf9,0x7d,0xf2,0xef,0xbe,0xdb,0x99,0x1e,0x47,0x7b,0xa3,0x56,0x55,0x3b,0x95,0x81,0xd5,0x7a,0x2c,0xa4,0xfc,0xf7,0xcc,0xf3,0x33,0x43,0x6e,0x28,0x14,0x32,0x9d,0x97,0x0b,0x34,0x0d,0x9d,0xc2,0xb6,0xe1,0x07,0x73,0x56,0x48,0x1a,0x77,0x31,0x82,0xd4,0x4d,0xe1,0x24,0xc5,0xb0,0x32,0xb6,0xa4,0x2b,0x1a,0x54,0x51,0xb3,0xed,0xf3,0x5a,0x2b,0x28,0x48,0x60,0xd1,0xa3,0xeb,0x36,0x73,0x7a,0xd2,0x79,0xc0,0x4f},
+    {0x7f,0x2f,0xbf,0x89,0xb0,0x38,0xc9,0x51,0xa7,0xe9,0xdf,0x02,0x65,0xbd,0x97,0x24,0x53,0xe4,0x80,0x78,0x9c,0xc0,0xff,0xff,0x92,0x8e,0xf9,0xca,0xce,0x67,0x45,0x12,0x0d,0xc5,0x86,0x0c,0x44,0x8b,0x34,0xdc,0x51,0xe6,0x94,0xcc,0xc9,0xcb,0x37,0x13,0xb9,0x3c,0x3e,0x64,0x4d,0xf7,0x22,0x64,0x08,0xcd,0xe3,0xba,0xc2,0x70,0x11,0x24,0xb4,0x73,0xc4,0x0a,0x86,0xab,0xf9,0x3f,0x35,0xe4,0x13,0x01,0xee,0x1d,0x91,0xf0,0xaf,0xc4,0xc6,0xeb,0x60,0x50,0xe7,0x4a,0x0d,0x00,0x87,0x6c,0x96,0x12,0x86,0x3f},
+    {0xde,0x0d,0x2a,0x78,0xc9,0x0c,0x9a,0x55,0x85,0x83,0x71,0xea,0xb2,0xcd,0x1d,0x55,0x8c,0x23,0xef,0x31,0x5b,0x86,0x62,0x7f,0x3d,0x61,0x73,0x79,0x76,0xa7,0x4a,0x50,0x13,0x8d,0x04,0x36,0xfa,0xfc,0x18,0x9c,0xdd,0x9d,0x89,0x73,0xb3,0x9d,0x15,0x29,0xaa,0xd0,0x92,0x9f,0x0b,0x35,0x9f,0xdc,0xd4,0x19,0x8a,0x87,0xee,0x7e,0xf5,0x26,0xb1,0xef,0x87,0x56,0xd5,0x2c,0xab,0x0c,0x7b,0xf1,0x7a,0x24,0x62,0xd1,0x80,0x51,0x67,0x24,0x5a,0x4f,0x34,0x5a,0xc1,0x85,0x69,0x30,0xba,0x9d,0x3d,0x94,0x41,0x40},
+    {0x96,0xcc,0xeb,0x43,0xba,0xee,0xc0,0xc3,0xaf,0x9c,0xea,0x26,0x9c,0x9c,0x74,0x8d,0xc6,0xcc,0x77,0x1c,0xee,0x95,0xfa,0xd9,0x0f,0x34,0x84,0x76,0xd9,0xa1,0x20,0x14,0xdd,0xaa,0x6c,0xa2,0x43,0x77,0x21,0x4b,0xce,0xb7,0x8a,0x64,0x24,0xb4,0xa6,0x47,0xe3,0xc9,0xfb,0x03,0x7a,0x4f,0x1d,0xcb,0x19,0xd0,0x00,0x98,0x42,0x31,0xd9,0x12,0x4f,0x59,0x37,0xd3,0x99,0x77,0xc6,0x00,0x7b,0xa4,0x3a,0xb2,0x40,0x51,0x3c,0x5e,0x95,0xf3,0x5f,0xe3,0x54,0x28,0x18,0x44,0x12,0xa0,0x59,0x43,0x31,0x92,0x4f,0x1b},
+    {0x51,0x09,0x15,0x89,0x9d,0x10,0x5c,0x3e,0x6a,0x69,0xe9,0x2d,0x91,0xfa,0xce,0x39,0x20,0x30,0x5f,0x97,0x3f,0xe4,0xea,0x20,0xae,0x2d,0x13,0x7f,0x2a,0x57,0x9b,0x23,0xb1,0x66,0x98,0xa4,0x30,0x30,0xcf,0x33,0x59,0x48,0x5f,0x21,0xd2,0x73,0x1f,0x25,0xf6,0xf4,0xde,0x51,0x40,0xaa,0x82,0xab,0xf6,0x23,0x9a,0x6f,0xd5,0x91,0xf1,0x5f,0x68,0x90,0x2d,0xac,0x33,0xd4,0x9e,0x81,0x23,0x85,0xc9,0x5f,0x79,0xab,0x83,0x28,0x3d,0xeb,0x93,0x55,0x80,0x72,0x45,0xef,0xcb,0x36,0x8f,0x75,0x6a,0x52,0x0c,0x02},
+    {0xbc,0xdb,0xd8,0x9e,0xf8,0x34,0x98,0x77,0x6c,0xa4,0x7c,0xdc,0xf9,0xaa,0xf2,0xc8,0x74,0xb0,0xe1,0xa3,0xdc,0x4c,0x52,0xa9,0x77,0x38,0x31,0x15,0x46,0xcc,0xaa,0x02,0x89,0xcc,0x42,0xf0,0x59,0xef,0x31,0xe9,0xb6,0x4b,0x12,0x8e,0x9d,0x9c,0x58,0x2c,0x97,0x59,0xc7,0xae,0x8a,0xe1,0xc8,0xad,0x0c,0xc5,0x02,0x56,0x0a,0xfe,0x2c,0x45,0xdf,0x77,0x78,0x64,0xa0,0xf7,0xa0,0x86,0x9f,0x7c,0x60,0x0e,0x27,0x64,0xc4,0xbb,0xc9,0x11,0xfb,0xf1,0x25,0xea,0x17,0xab,0x7b,0x87,0x4b,0x30,0x7b,0x7d,0xfb,0x4c},
+    {0xfe,0x75,0x9b,0xb8,0x6c,0x3d,0xb4,0x72,0x80,0xdc,0x6a,0x9c,0xd9,0x94,0xc6,0x54,0x9f,0x4c,0xe3,0x3e,0x37,0xaa,0xc3,0xb8,0x64,0x53,0x07,0x39,0x2b,0x62,0xb4,0x14,0x12,0xef,0x89,0x97,0xc2,0x99,0x86,0xe2,0x0d,0x19,0x57,0xdf,0x71,0xcd,0x6e,0x2b,0xd0,0x70,0xc9,0xec,0x57,0xc8,0x43,0xc3,0xc5,0x3a,0x4d,0x43,0xbc,0x4c,0x1d,0x5b,0x26,0x9f,0x0a,0xcc,0x15,0x26,0xfb,0xb6,0xe5,0xcc,0x8d,0xb8,0x2b,0x0e,0x4f,0x3a,0x05,0xa7,0x69,0x33,0x8b,0x49,0x01,0x13,0xd1,0x2d,0x59,0x58,0x12,0xf7,0x98,0x2f},
+    {0x56,0x9e,0x0f,0xb5,0x4c,0xa7,0x94,0x0c,0x20,0x13,0x8e,0x8e,0xa9,0xf4,0x1f,0x5b,0x67,0x0f,0x30,0x82,0x21,0xcc,0x2a,0x9a,0xf9,0xaa,0x06,0xd8,0x49,0xe2,0x6a,0x3a,0x01,0xa7,0x54,0x4f,0x44,0xae,0x12,0x2e,0xde,0xd7,0xcb,0xa9,0xf0,0x3e,0xfe,0xfc,0xe0,0x5d,0x83,0x75,0x0d,0x89,0xbf,0xce,0x54,0x45,0x61,0xe7,0xe9,0x62,0x80,0x1d,0x5a,0x7c,0x90,0xa9,0x85,0xda,0x7a,0x65,0x62,0x0f,0xb9,0x91,0xb5,0xa8,0x0e,0x1a,0xe9,0xb4,0x34,0xdf,0xfb,0x1d,0x0e,0x8d,0xf3,0x5f,0xf2,0xae,0xe8,0x8c,0x8b,0x29},
+    {0xb2,0x0c,0xf7,0xef,0x53,0x79,0x92,0x2a,0x76,0x70,0x15,0x79,0x2a,0xc9,0x89,0x4b,0x6a,0xcf,0xa7,0x30,0x7a,0x45,0x18,0x94,0x85,0xe4,0x5c,0x4d,0x40,0xa8,0xb8,0x34,0xde,0x65,0x21,0x0a,0xea,0x72,0x7a,0x83,0xf6,0x79,0xcf,0x0b,0xb4,0x07,0xab,0x3f,0x70,0xae,0x38,0x77,0xc7,0x36,0x16,0x52,0xdc,0xd7,0xa7,0x03,0x18,0x27,0xa6,0x6b,0x35,0x33,0x69,0x83,0xb5,0xec,0x6e,0xc2,0xfd,0xfe,0xb5,0x63,0xdf,0x13,0xa8,0xd5,0x73,0x25,0xb2,0xa4,0x9a,0xaa,0x93,0xa2,0x6a,0x1c,0x5e,0x46,0xdd,0x2b,0xd6,0x71},
+    {0x80,0xdf,0x78,0xd3,0x28,0xcc,0x33,0x65,0xb4,0xa4,0x0f,0x0a,0x79,0x43,0xdb,0xf6,0x5a,0xda,0x01,0xf7,0xf9,0x5f,0x64,0xe3,0xa4,0x2b,0x17,0xf3,0x17,0xf3,0xd5,0x74,0xf5,0x5e,0xf7,0xb1,0xda,0xb5,0x2d,0xcd,0xf5,0x65,0xb0,0x16,0xcf,0x95,0x7f,0xd7,0x85,0xf0,0x49,0x3f,0xea,0x1f,0x57,0x14,0x3d,0x2b,0x2b,0x26,0x21,0x36,0x33,0x1c,0x81,0xca,0xd9,0x67,0x54,0xe5,0x6f,0xa8,0x37,0x8c,0x29,0x2b,0x75,0x7c,0x8b,0x39,0x3b,0x62,0xac,0xe3,0x92,0x08,0x6d,0xda,0x8c,0xd9,0xe9,0x47,0x45,0xcc,0xeb,0x4a},
+    {0xc9,0x01,0x6d,0x27,0x1b,0x07,0xf0,0x12,0x70,0x8c,0xc4,0x86,0xc5,0xba,0xb8,0xe7,0xa9,0xfb,0xd6,0x71,0x9b,0x12,0x08,0x53,0x92,0xb7,0x3d,0x5a,0xf9,0xfb,0x88,0x5d,0x10,0xb6,0x54,0x73,0x9e,0x8d,0x40,0x0b,0x6e,0x5b,0xa8,0x5b,0x53,0x32,0x6b,0x80,0x07,0xa2,0x58,0x4a,0x03,0x3a,0xe6,0xdb,0x2c,0xdf,0xa1,0xc9,0xdd,0xd9,0x3b,0x17,0xdf,0x72,0x58,0xfe,0x1e,0x0f,0x50,0x2b,0xc1,0x18,0x39,0xd4,0x2e,0x58,0xd6,0x58,0xe0,0x3a,0x67,0xc9,0x8e,0x27,0xed,0xe6,0x19,0xa3,0x9e,0xb1,0x13,0xcd,0xe1,0x06},
+    {0x23,0x6f,0x16,0x6f,0x51,0xad,0xd0,0x40,0xbe,0x6a,0xab,0x1f,0x93,0x32,0x8e,0x11,0x8e,0x08,0x4d,0xa0,0x14,0x5e,0xe3,0x3f,0x66,0x62,0xe1,0x26,0x35,0x60,0x80,0x30,0x53,0x03,0x5b,0x9e,0x62,0xaf,0x2b,0x47,0x47,0x04,0x8d,0x27,0x90,0x0b,0xaa,0x3b,0x27,0xbf,0x43,0x96,0x46,0x5f,0x78,0x0c,0x13,0x7b,0x83,0x8d,0x1a,0x6a,0x3a,0x7f,0x0b,0x80,0x3d,0x5d,0x39,0x44,0xe6,0xf7,0xf6,0xed,0x01,0xc9,0x55,0xd5,0xa8,0x95,0x39,0x63,0x2c,0x59,0x30,0x78,0xcd,0x68,0x7e,0x30,0x51,0x2e,0xed,0xfd,0xd0,0x30},
+    {0xb3,0x33,0x12,0xf2,0x1a,0x4d,0x59,0xe0,0x9c,0x4d,0xcc,0xf0,0x8e,0xe7,0xdb,0x1b,0x77,0x9a,0x49,0x8f,0x7f,0x18,0x65,0x69,0x68,0x98,0x09,0x2c,0x20,0x14,0x92,0x0a,0x50,0x47,0xb8,0x68,0x1e,0x97,0xb4,0x9c,0xcf,0xbb,0x64,0x66,0x29,0x72,0x95,0xa0,0x2b,0x41,0xfa,0x72,0x26,0xe7,0x8d,0x5c,0xd9,0x89,0xc5,0x51,0x43,0x08,0x15,0x46,0x2e,0xa0,0xb9,0xae,0xc0,0x19,0x90,0xbc,0xae,0x4c,0x03,0x16,0x0d,0x11,0xc7,0x55,0xec,0x32,0x99,0x65,0x01,0xf5,0x6d,0x0e,0xfe,0x5d,0xca,0x95,0x28,0x0d,0xca,0x3b},
+    {0xa4,0x62,0x5d,0x3c,0xbc,0x31,0xf0,0x40,0x60,0x7a,0xf0,0xcf,0x3e,0x8b,0xfc,0x19,0x45,0xb5,0x0f,0x13,0xa2,0x3d,0x18,0x98,0xcd,0x13,0x8f,0xae,0xdd,0xde,0x31,0x56,0xbf,0x01,0xcc,0x9e,0xb6,0x8e,0x68,0x9c,0x6f,0x89,0x44,0xa6,0xad,0x83,0xbc,0xf0,0xe2,0x9f,0x7a,0x5f,0x5f,0x95,0x2d,0xca,0x41,0x82,0xf2,0x8d,0x03,0xb4,0xa8,0x4e,0x02,0xd2,0xca,0xf1,0x0a,0x46,0xed,0x2a,0x83,0xee,0x8c,0xa4,0x05,0x53,0x30,0x46,0x5f,0x1a,0xf1,0x49,0x45,0x77,0x21,0x91,0x63,0xa4,0x2c,0x54,0x30,0x09,0xce,0x24},
+    {0x06,0xc1,0x06,0xfd,0xf5,0x90,0xe8,0x1f,0xf2,0x10,0x88,0x5d,0x35,0x68,0xc4,0xb5,0x3e,0xaf,0x8c,0x6e,0xfe,0x08,0x78,0x82,0x4b,0xd7,0x06,0x8a,0xc2,0xe3,0xd4,0x41,0x85,0x0b,0xf3,0xfd,0x55,0xa1,0xcf,0x3f,0xa4,0x2e,0x37,0x36,0x8e,0x16,0xf7,0xd2,0x44,0xf8,0x92,0x64,0xde,0x64,0xe0,0xb2,0x80,0x42,0x4f,0x32,0xa7,0x28,0x99,0x54,0x2e,0x1a,0xee,0x63,0xa7,0x32,0x6e,0xf2,0xea,0xfd,0x5f,0xd2,0xb7,0xe4,0x91,0xae,0x69,0x4d,0x7f,0xd1,0x3b,0xd3,0x3b,0xbc,0x6a,0xff,0xdc,0xc0,0xde,0x66,0x1b,0x49},
+    {0xa7,0x32,0xea,0xc7,0x3d,0xb1,0xf5,0x98,0x98,0xdb,0x16,0x7e,0xcc,0xf8,0xd5,0xe3,0x47,0xd9,0xf8,0xcb,0x52,0xbf,0x0a,0xac,0xac,0xe4,0x5e,0xc8,0xd0,0x38,0xf3,0x08,0xa1,0x64,0xda,0xd0,0x8e,0x4a,0xf0,0x75,0x4b,0x28,0xe2,0x67,0xaf,0x2c,0x22,0xed,0xa4,0x7b,0x7b,0x1f,0x79,0xa3,0x34,0x82,0x67,0x8b,0x01,0xb7,0xb0,0xb8,0xf6,0x4c,0xbd,0x73,0x1a,0x99,0x21,0xa8,0x83,0xc3,0x7a,0x0c,0x32,0xdf,0x01,0xbc,0x27,0xab,0x63,0x70,0x77,0x84,0x1b,0x33,0x3d,0xc1,0x99,0x8a,0x07,0xeb,0x82,0x4a,0x0d,0x53},
+    {0x25,0x48,0xf9,0xe1,0x30,0x36,0x4c,0x00,0x5a,0x53,0xab,0x8c,0x26,0x78,0x2d,0x7e,0x8b,0xff,0x84,0xcc,0x23,0x23,0x48,0xc7,0xb9,0x70,0x17,0x10,0x3f,0x75,0xea,0x65,0x9e,0xbf,0x9a,0x6c,0x45,0x73,0x69,0x6d,0x80,0xa8,0x00,0x49,0xfc,0xb2,0x7f,0x25,0x50,0xb8,0xcf,0xc8,0x12,0xf4,0xac,0x2b,0x5b,0xbd,0xbf,0x0c,0xe0,0xe7,0xb3,0x0d,0x63,0x63,0x09,0xe2,0x3e,0xfc,0x66,0x3d,0x6b,0xcb,0xb5,0x61,0x7f,0x2c,0xd6,0x81,0x1a,0x3b,0x44,0x13,0x42,0x04,0xbe,0x0f,0xdb,0xa1,0xe1,0x21,0x19,0xec,0xa4,0x02},
+    {0xa2,0xb8,0x24,0x3b,0x9a,0x25,0xe6,0x5c,0xb8,0xa0,0xaf,0x45,0xcc,0x7a,0x57,0xb8,0x37,0x70,0xa0,0x8b,0xe8,0xe6,0xcb,0xcc,0xbf,0x09,0x78,0x12,0x51,0x3c,0x14,0x3d,0x5f,0x79,0xcf,0xf1,0x62,0x61,0xc8,0xf5,0xf2,0x57,0xee,0x26,0x19,0x86,0x8c,0x11,0x78,0x35,0x06,0x1c,0x85,0x24,0x21,0x17,0xcf,0x7f,0x06,0xec,0x5d,0x2b,0xd1,0x36,0x57,0x45,0x15,0x79,0x91,0x27,0x6d,0x12,0x0a,0x3a,0x78,0xfc,0x5c,0x8f,0xe4,0xd5,0xac,0x9b,0x17,0xdf,0xe8,0xb6,0xbd,0x36,0x59,0x28,0xa8,0x5b,0x88,0x17,0xf5,0x2e},
+    {0xdc,0xae,0x58,0x8c,0x4e,0x97,0x37,0x46,0xa4,0x41,0xf0,0xab,0xfb,0x22,0xef,0xb9,0x8a,0x71,0x80,0xe9,0x56,0xd9,0x85,0xe1,0xa6,0xa8,0x43,0xb1,0xfa,0x78,0x1b,0x2f,0x51,0x2f,0x5b,0x30,0xfb,0xbf,0xee,0x96,0xb8,0x96,0x95,0x88,0xad,0x38,0xf9,0xd3,0x25,0xdd,0xd5,0x46,0xc7,0x2d,0xf5,0xf0,0x95,0x00,0x3a,0xbb,0x90,0x82,0x96,0x57,0x01,0xe1,0x20,0x0a,0x43,0xb8,0x1a,0xf7,0x47,0xec,0xf0,0x24,0x8d,0x65,0x93,0xf3,0xd1,0xee,0xe2,0x6e,0xa8,0x09,0x75,0xcf,0xe1,0xa3,0x2a,0xdc,0x35,0x3e,0xc4,0x7d},
+    {0xc3,0xd9,0x7d,0x88,0x65,0x66,0x96,0x85,0x55,0x53,0xb0,0x4b,0x31,0x9b,0x0f,0xc9,0xb1,0x79,0x20,0xef,0xf8,0x8d,0xe0,0xc6,0x2f,0xc1,0x8c,0x75,0x16,0x20,0xf7,0x7e,0x18,0x97,0x3e,0x27,0x5c,0x2a,0x78,0x5a,0x94,0xfd,0x4e,0x5e,0x99,0xc6,0x76,0x35,0x3e,0x7d,0x23,0x1f,0x05,0xd8,0x2e,0x0f,0x99,0x0a,0xd5,0x82,0x1d,0xb8,0x4f,0x04,0xd9,0xe3,0x07,0xa9,0xc5,0x18,0xdf,0xc1,0x59,0x63,0x4c,0xce,0x1d,0x37,0xb3,0x57,0x49,0xbb,0x01,0xb2,0x34,0x45,0x70,0xca,0x2e,0xdd,0x30,0x9c,0x3f,0x82,0x79,0x7f},
+    {0xe8,0x13,0xb5,0xa3,0x39,0xd2,0x34,0x83,0xd8,0xa8,0x1f,0xb9,0xd4,0x70,0x36,0xc1,0x33,0xbd,0x90,0xf5,0x36,0x41,0xb5,0x12,0xb4,0xd9,0x84,0xd7,0x73,0x03,0x4e,0x0a,0xba,0x87,0xf5,0x68,0xf0,0x1f,0x9c,0x6a,0xde,0xc8,0x50,0x00,0x4e,0x89,0x27,0x08,0xe7,0x5b,0xed,0x7d,0x55,0x99,0xbf,0x3c,0xf0,0xd6,0x06,0x1c,0x43,0xb0,0xa9,0x64,0x19,0x29,0x7d,0x5b,0xa1,0xd6,0xb3,0x2e,0x35,0x82,0x3a,0xd5,0xa0,0xf6,0xb4,0xb0,0x47,0x5d,0xa4,0x89,0x43,0xce,0x56,0x71,0x6c,0x34,0x18,0xce,0x0a,0x7d,0x1a,0x07},
+    {0x0b,0xba,0x87,0xc8,0xaa,0x2d,0x07,0xd3,0xee,0x62,0xa5,0xbf,0x05,0x29,0x26,0x01,0x8b,0x76,0xef,0xc0,0x02,0x30,0x54,0xcf,0x9c,0x7e,0xea,0x46,0x71,0xcc,0x3b,0x2c,0x31,0x44,0xe1,0x20,0x52,0x35,0x0c,0xcc,0x41,0x51,0xb1,0x09,0x07,0x95,0x65,0x0d,0x36,0x5f,0x9d,0x20,0x1b,0x62,0xf5,0x9a,0xd3,0x55,0x77,0x61,0xf7,0xbc,0x69,0x7c,0x5f,0x29,0xe8,0x04,0xeb,0xd7,0xf0,0x07,0x7d,0xf3,0x50,0x2f,0x25,0x18,0xdb,0x10,0xd7,0x98,0x17,0x17,0xa3,0xa9,0x51,0xe9,0x1d,0xa5,0xac,0x22,0x73,0x9a,0x5a,0x6f},
+    {0xc5,0xc6,0x41,0x2f,0x0c,0x00,0xa1,0x8b,0x9b,0xfb,0xfe,0x0c,0xc1,0x79,0x9f,0xc4,0x9f,0x1c,0xc5,0x3c,0x70,0x47,0xfa,0x4e,0xca,0xaf,0x47,0xe1,0xa2,0x21,0x4e,0x49,0xbe,0x44,0xd9,0xa3,0xeb,0xd4,0x29,0xe7,0x9e,0xaf,0x78,0x80,0x40,0x09,0x9e,0x8d,0x03,0x9c,0x86,0x47,0x7a,0x56,0x25,0x45,0x24,0x3b,0x8d,0xee,0x80,0x96,0xab,0x02,0x9a,0x0d,0xe5,0xdd,0x85,0x8a,0xa4,0xef,0x49,0xa2,0xb9,0x0f,0x4e,0x22,0x9a,0x21,0xd9,0xf6,0x1e,0xd9,0x1d,0x1f,0x09,0xfa,0x34,0xbb,0x46,0xea,0xcb,0x76,0x5d,0x6b},
+    {0x94,0xd9,0x0c,0xec,0x6c,0x55,0x57,0x88,0xba,0x1d,0xd0,0x5c,0x6f,0xdc,0x72,0x64,0x77,0xb4,0x42,0x8f,0x14,0x69,0x01,0xaf,0x54,0x73,0x27,0x85,0xf6,0x33,0xe3,0x0a,0x22,0x25,0x78,0x1e,0x17,0x41,0xf9,0xe0,0xd3,0x36,0x69,0x03,0x74,0xae,0xe6,0xf1,0x46,0xc7,0xfc,0xd0,0xa2,0x3e,0x8b,0x40,0x3e,0x31,0xdd,0x03,0x9c,0x86,0xfb,0x16,0x62,0x09,0xb6,0x33,0x97,0x19,0x8e,0x28,0x33,0xe1,0xab,0xd8,0xb4,0x72,0xfc,0x24,0x3e,0xd0,0x91,0x09,0xed,0xf7,0x11,0x48,0x75,0xd0,0x70,0x8f,0x8b,0xe3,0x81,0x3f},
+    {0xfe,0xaf,0xd9,0x7e,0xcc,0x0f,0x91,0x7f,0x4b,0x87,0x65,0x24,0xa1,0xb8,0x5c,0x54,0x04,0x47,0x0c,0x4b,0xd2,0x7e,0x39,0xa8,0x93,0x09,0xf5,0x04,0xc1,0x0f,0x51,0x50,0x24,0xc8,0x17,0x5f,0x35,0x7f,0xdb,0x0a,0xa4,0x99,0x42,0xd7,0xc3,0x23,0xb9,0x74,0xf7,0xea,0xf8,0xcb,0x8b,0x3e,0x7c,0xd5,0x3d,0xdc,0xde,0x4c,0xd3,0xe2,0xd3,0x0a,0x9d,0x24,0x6e,0x33,0xc5,0x0f,0x0c,0x6f,0xd9,0xcf,0x31,0xc3,0x19,0xde,0x5e,0x74,0x1c,0xfe,0xee,0x09,0x00,0xfd,0xd6,0xf2,0xbe,0x1e,0xfa,0xf0,0x8b,0x15,0x7c,0x12},
+    {0xa2,0x79,0x98,0x2e,0x42,0x7c,0x19,0xf6,0x47,0x36,0xca,0x52,0xd4,0xdd,0x4a,0xa4,0xcb,0xac,0x4e,0x4b,0xc1,0x3f,0x41,0x9b,0x68,0x4f,0xef,0x07,0x7d,0xf8,0x4e,0x35,0x74,0xb9,0x51,0xae,0xc4,0x8f,0xa2,0xde,0x96,0xfe,0x4d,0x74,0xd3,0x73,0x99,0x1d,0xa8,0x48,0x38,0x87,0x0b,0x68,0x40,0x62,0x95,0xdf,0x67,0xd1,0x79,0x24,0xd8,0x4e,0x75,0xd9,0xc5,0x60,0x22,0xb5,0xe3,0xfe,0xb8,0xb0,0x41,0xeb,0xfc,0x2e,0x35,0x50,0x3c,0x65,0xf6,0xa9,0x30,0xac,0x08,0x88,0x6d,0x23,0x39,0x05,0xd2,0x92,0x2d,0x30},
+    {0x3d,0x28,0xa4,0xbc,0xa2,0xc1,0x13,0x78,0xd9,0x3d,0x86,0xa1,0x91,0xf0,0x62,0xed,0x86,0xfa,0x68,0xc2,0xb8,0xbc,0xc7,0xae,0x4c,0xae,0x1c,0x6f,0xb7,0xd3,0xe5,0x10,0x77,0xf1,0xe0,0xe4,0xb6,0x6f,0xbc,0x2d,0x93,0x6a,0xbd,0xa4,0x29,0xbf,0xe1,0x04,0xe8,0xf6,0x7a,0x78,0xd4,0x66,0x19,0x5e,0x60,0xd0,0x26,0xb4,0x5e,0x5f,0xdc,0x0e,0x67,0x8e,0xda,0x53,0xd6,0xbf,0x53,0x54,0x41,0xf6,0xa9,0x24,0xec,0x1e,0xdc,0xe9,0x23,0x8a,0x57,0x03,0x3b,0x26,0x87,0xbf,0x72,0xba,0x1c,0x36,0x51,0x6c,0xb4,0x45},
+    {0xa1,0x7f,0x4f,0x31,0xbf,0x2a,0x40,0xa9,0x50,0xf4,0x8c,0x8e,0xdc,0xf1,0x57,0xe2,0x84,0xbe,0xa8,0x23,0x4b,0xd5,0xbb,0x1d,0x3b,0x71,0xcb,0x6d,0xa3,0xbf,0x77,0x21,0xe4,0xe3,0x7f,0x8a,0xdd,0x4d,0x9d,0xce,0x30,0x0e,0x62,0x76,0x56,0x64,0x13,0xab,0x58,0x99,0x0e,0xb3,0x7b,0x4f,0x59,0x4b,0xdf,0x29,0x12,0x32,0xef,0x0a,0x1c,0x5c,0x8f,0xdb,0x79,0xfa,0xbc,0x1b,0x08,0x37,0xb3,0x59,0x5f,0xc2,0x1e,0x81,0x48,0x60,0x87,0x24,0x83,0x9c,0x65,0x76,0x7a,0x08,0xbb,0xb5,0x8a,0x7d,0x38,0x19,0xe6,0x4a},
+    {0x2e,0xa3,0x44,0x53,0xaa,0xf6,0xdb,0x8d,0x78,0x40,0x1b,0xb4,0xb4,0xea,0x88,0x7d,0x60,0x0d,0x13,0x4a,0x97,0xeb,0xb0,0x5e,0x03,0x3e,0xbf,0x17,0x1b,0xd9,0x00,0x1a,0x83,0xfb,0x5b,0x98,0x44,0x7e,0x11,0x61,0x36,0x31,0x96,0x71,0x2a,0x46,0xe0,0xfc,0x4b,0x90,0x25,0xd4,0x48,0x34,0xac,0x83,0x64,0x3d,0xa4,0x5b,0xbe,0x5a,0x68,0x75,0xb2,0xf2,0x61,0xeb,0x33,0x09,0x96,0x6e,0x52,0x49,0xff,0xc9,0xa8,0x0f,0x3d,0x54,0x69,0x65,0xf6,0x7a,0x10,0x75,0x72,0xdf,0xaa,0xe6,0xb0,0x23,0xb6,0x29,0x55,0x13},
+    {0x18,0xd5,0xd1,0xad,0xd7,0xdb,0xf0,0x18,0x11,0x1f,0xc1,0xcf,0x88,0x78,0x9f,0x97,0x9b,0x75,0x14,0x71,0xf0,0xe1,0x32,0x87,0x01,0x3a,0xca,0x65,0x1a,0xb8,0xb5,0x79,0xfe,0x83,0x2e,0xe2,0xbc,0x16,0xc7,0xf5,0xc1,0x85,0x09,0xe8,0x19,0xeb,0x2b,0xb4,0xae,0x4a,0x25,0x14,0x37,0xa6,0x9d,0xec,0x13,0xa6,0x90,0x15,0x05,0xea,0x72,0x59,0x11,0x78,0x8f,0xdc,0x20,0xac,0xd4,0x0f,0xa8,0x4f,0x4d,0xac,0x94,0xd2,0x9a,0x9a,0x34,0x04,0x36,0xb3,0x64,0x2d,0x1b,0xc0,0xdb,0x3b,0x5f,0x90,0x95,0x9c,0x7e,0x4f},
+    {0x2e,0x30,0x81,0x57,0xbc,0x4b,0x67,0x62,0x0f,0xdc,0xad,0x89,0x39,0x0f,0x52,0xd8,0xc6,0xd9,0xfb,0x53,0xae,0x99,0x29,0x8c,0x4c,0x8e,0x63,0x2e,0xd9,0x3a,0x99,0x31,0xfe,0x99,0x52,0x35,0x3d,0x44,0xc8,0x71,0xd7,0xea,0xeb,0xdb,0x1c,0x3b,0xcd,0x8b,0x66,0x94,0xa4,0xf1,0x9e,0x49,0x92,0x80,0xc8,0xad,0x44,0xa1,0xc4,0xee,0x42,0x19,0x92,0x49,0x23,0xae,0x19,0x53,0xac,0x7d,0x92,0x3e,0xea,0x0c,0x91,0x3d,0x1b,0x2c,0x22,0x11,0x3c,0x25,0x94,0xe4,0x3c,0x55,0x75,0xca,0xf9,0x4e,0x31,0x65,0x0a,0x2a},
+    {0xc2,0x27,0xf9,0xf7,0x7f,0x93,0xb7,0x2d,0x35,0xa6,0xd0,0x17,0x06,0x1f,0x74,0xdb,0x76,0xaf,0x55,0x11,0xa2,0xf3,0x82,0x59,0xed,0x2d,0x7c,0x64,0x18,0xe2,0xf6,0x4c,0x3a,0x79,0x1c,0x3c,0xcd,0x1a,0x36,0xcf,0x3b,0xbc,0x35,0x5a,0xac,0xbc,0x9e,0x2f,0xab,0xa6,0xcd,0xa8,0xe9,0x60,0xe8,0x60,0x13,0x1a,0xea,0x6d,0x9b,0xc3,0x5d,0x05,0xb6,0x5b,0x8d,0xc2,0x7c,0x22,0x19,0xb1,0xab,0xff,0x4d,0x77,0xbc,0x4e,0xe2,0x07,0x89,0x2c,0xa3,0xe4,0xce,0x78,0x3c,0xa8,0xb6,0x24,0xaa,0x10,0x77,0x30,0x1a,0x12},
+    {0x97,0x4a,0x03,0x9f,0x5e,0x5d,0xdb,0xe4,0x2d,0xbc,0x34,0x30,0x09,0xfc,0x53,0xe1,0xb1,0xd3,0x51,0x95,0x91,0x46,0x05,0x46,0x2d,0xe5,0x40,0x7a,0x6c,0xc7,0x3f,0x33,0xc9,0x83,0x74,0xc7,0x3e,0x71,0x59,0xd6,0xaf,0x96,0x2b,0xb8,0x77,0xe0,0xbf,0x88,0xd3,0xbc,0x97,0x10,0x23,0x28,0x9e,0x28,0x9b,0x3a,0xed,0x6c,0x4a,0xb9,0x7b,0x52,0x2e,0x48,0x5b,0x99,0x2a,0x99,0x3d,0x56,0x01,0x38,0x38,0x6e,0x7c,0xd0,0x05,0x34,0xe5,0xd8,0x64,0x2f,0xde,0x35,0x50,0x48,0xf7,0xa9,0xa7,0x20,0x9b,0x06,0x89,0x6b},
+    {0x0d,0x22,0x70,0x62,0x41,0xa0,0x2a,0x81,0x4e,0x5b,0x24,0xf9,0xfa,0x89,0x5a,0x99,0x05,0xef,0x72,0x50,0xce,0xc4,0xad,0xff,0x73,0xeb,0x73,0xaa,0x03,0x21,0xbc,0x23,0x77,0xdb,0xc7,0xb5,0x8c,0xfa,0x82,0x40,0x55,0xc1,0x34,0xc7,0xf8,0x86,0x86,0x06,0x7e,0xa5,0xe7,0xf6,0xd9,0xc8,0xe6,0x29,0xcf,0x9b,0x63,0xa7,0x08,0xd3,0x73,0x04,0x05,0x9e,0x58,0x03,0x26,0x79,0xee,0xca,0x92,0xc4,0xdc,0x46,0x12,0x42,0x4b,0x2b,0x4f,0xa9,0x01,0xe6,0x74,0xef,0xa1,0x02,0x1a,0x34,0x04,0xde,0xbf,0x73,0x2f,0x10},
+    {0xc6,0x45,0x57,0x7f,0xab,0xb9,0x18,0xeb,0x90,0xc6,0x87,0x57,0xee,0x8a,0x3a,0x02,0xa9,0xaf,0xf7,0x2d,0xda,0x12,0x27,0xb7,0x3d,0x01,0x5c,0xea,0x25,0x7d,0x59,0x36,0x9a,0x1c,0x51,0xb5,0xe0,0xda,0xb4,0xa2,0x06,0xff,0xff,0x2b,0x29,0x60,0xc8,0x7a,0x34,0x42,0x50,0xf5,0x5d,0x37,0x1f,0x98,0x2d,0xa1,0x4e,0xda,0x25,0xd7,0x6b,0x3f,0xac,0x58,0x60,0x10,0x7b,0x8d,0x4d,0x73,0x5f,0x90,0xc6,0x6f,0x9e,0x57,0x40,0xd9,0x2d,0x93,0x02,0x92,0xf9,0xf8,0x66,0x64,0xd0,0xd6,0x60,0xda,0x19,0xcc,0x7e,0x7b},
+    {0x0d,0x69,0x5c,0x69,0x3c,0x37,0xc2,0x78,0x6e,0x90,0x42,0x06,0x66,0x2e,0x25,0xdd,0xd2,0x2b,0xe1,0x4a,0x44,0x44,0x1d,0x95,0x56,0x39,0x74,0x01,0x76,0xad,0x35,0x42,0x9b,0xfa,0x7c,0xa7,0x51,0x4a,0xae,0x6d,0x50,0x86,0xa3,0xe7,0x54,0x36,0x26,0x82,0xdb,0x82,0x2d,0x8f,0xcd,0xff,0xbb,0x09,0xba,0xca,0xf5,0x1b,0x66,0xdc,0xbe,0x03,0xf5,0x75,0x89,0x07,0x0d,0xcb,0x58,0x62,0x98,0xf2,0x89,0x91,0x54,0x42,0x29,0x49,0xe4,0x6e,0xe3,0xe2,0x23,0xb4,0xca,0xa0,0xa1,0x66,0xf0,0xcd,0xb0,0xe2,0x7c,0x0e},
+    {0xa3,0x85,0x8c,0xc4,0x3a,0x64,0x94,0xc4,0xad,0x39,0x61,0x3c,0xf4,0x1d,0x36,0xfd,0x48,0x4d,0xe9,0x3a,0xdd,0x17,0xdb,0x09,0x4a,0x67,0xb4,0x8f,0x5d,0x0a,0x6e,0x66,0xf9,0x70,0x4b,0xd9,0xdf,0xfe,0xa6,0xfe,0x2d,0xba,0xfc,0xc1,0x51,0xc0,0x30,0xf1,0x89,0xab,0x2f,0x7f,0x7e,0xd4,0x82,0x48,0xb5,0xee,0xec,0x8a,0x13,0x56,0x52,0x61,0x0d,0xcb,0x70,0x48,0x4e,0xf6,0xbb,0x2a,0x6b,0x8b,0x45,0xaa,0xf0,0xbc,0x65,0xcd,0x5d,0x98,0xe8,0x75,0xba,0x4e,0xbe,0x9a,0xe4,0xde,0x14,0xd5,0x10,0xc8,0x0b,0x7f},
+    {0x6f,0x13,0xf4,0x26,0xa4,0x6b,0x00,0xb9,0x35,0x30,0xe0,0x57,0x9e,0x36,0x67,0x8d,0x28,0x3c,0x46,0x4f,0xd9,0xdf,0xc8,0xcb,0xf5,0xdb,0xee,0xf8,0xbc,0x8d,0x1f,0x0d,0xa0,0x13,0x72,0x73,0xad,0x9d,0xac,0x83,0x98,0x2e,0xf7,0x2e,0xba,0xf8,0xf6,0x9f,0x57,0x69,0xec,0x43,0xdd,0x2e,0x1e,0x31,0x75,0xab,0xc5,0xde,0x7d,0x90,0x3a,0x1d,0xdc,0x81,0xd0,0x3e,0x31,0x93,0x16,0xba,0x80,0x34,0x1b,0x85,0xad,0x9f,0x32,0x29,0xcb,0x21,0x03,0x03,0x3c,0x01,0x28,0x01,0xe3,0xfd,0x1b,0xa3,0x44,0x1b,0x01,0x00},
+    {0x0c,0x6c,0xc6,0x3f,0x6c,0xa0,0xdf,0x3f,0xd2,0x0d,0xd6,0x4d,0x8e,0xe3,0x40,0x5d,0x71,0x4d,0x8e,0x26,0x38,0x8b,0xe3,0x7a,0xe1,0x57,0x83,0x6e,0x91,0x8d,0xc4,0x3a,0x5c,0xa7,0x0a,0x6a,0x69,0x1f,0x56,0x16,0x6a,0xbd,0x52,0x58,0x5c,0x72,0xbf,0xc1,0xad,0x66,0x79,0x9a,0x7f,0xdd,0xa8,0x11,0x26,0x10,0x85,0xd2,0xa2,0x88,0xd9,0x63,0x2e,0x23,0xbd,0xaf,0x53,0x07,0x12,0x00,0x83,0xf6,0xd8,0xfd,0xb8,0xce,0x2b,0xe9,0x91,0x2b,0xe7,0x84,0xb3,0x69,0x16,0xf8,0x66,0xa0,0x68,0x23,0x2b,0xd5,0xfa,0x33},
+    {0x16,0x1e,0xe4,0xc5,0xc6,0x49,0x06,0x54,0x35,0x77,0x3f,0x33,0x30,0x64,0xf8,0x0a,0x46,0xe7,0x05,0xf3,0xd2,0xfc,0xac,0xb2,0xa7,0xdc,0x56,0xa2,0x29,0xf4,0xc0,0x16,0xe8,0xcf,0x22,0xc4,0xd0,0xc8,0x2c,0x8d,0xcb,0x3a,0xa1,0x05,0x7b,0x4f,0x2b,0x07,0x6f,0xa5,0xf6,0xec,0xe6,0xb6,0xfe,0xa3,0xe2,0x71,0x0a,0xb9,0xcc,0x55,0xc3,0x3c,0x31,0x91,0x3e,0x90,0x43,0x94,0xb6,0xe9,0xce,0x37,0x56,0x7a,0xcb,0x94,0xa4,0xb8,0x44,0x92,0xba,0xba,0xa4,0xd1,0x7c,0xc8,0x68,0x75,0xae,0x6b,0x42,0xaf,0x1e,0x63},
+    {0x9f,0xfe,0x66,0xda,0x10,0x04,0xe9,0xb3,0xa6,0xe5,0x16,0x6c,0x52,0x4b,0xdd,0x85,0x83,0xbf,0xf9,0x1e,0x61,0x97,0x3d,0xbc,0xb5,0x19,0xa9,0x1e,0x8b,0x64,0x99,0x55,0xe8,0x0d,0x70,0xa3,0xb9,0x75,0xd9,0x47,0x52,0x05,0xf8,0xe2,0xfb,0xc5,0x80,0x72,0xe1,0x5d,0xe4,0x32,0x27,0x8f,0x65,0x53,0xb5,0x80,0x5f,0x66,0x7f,0x2c,0x1f,0x43,0x19,0x7b,0x8f,0x85,0x44,0x63,0x02,0xd6,0x4a,0x51,0xea,0xa1,0x2f,0x35,0xab,0x14,0xd7,0xa9,0x90,0x20,0x1a,0x44,0x00,0x89,0x26,0x3b,0x25,0x91,0x5f,0x71,0x04,0x7b},
+    {0x43,0xae,0xf6,0xac,0x28,0xbd,0xed,0x83,0xb4,0x7a,0x5c,0x7d,0x8b,0x7c,0x35,0x86,0x44,0x2c,0xeb,0xb7,0x69,0x47,0x40,0xc0,0x3f,0x58,0xf6,0xc2,0xf5,0x7b,0xb3,0x59,0xc6,0xba,0xe6,0xc4,0x80,0xc2,0x76,0xb3,0x0b,0x9b,0x1d,0x6d,0xdd,0xd3,0x0e,0x97,0x44,0xf9,0x0b,0x45,0x58,0x95,0x9a,0xb0,0x23,0xe2,0xcd,0x57,0xfa,0xac,0xd0,0x48,0x71,0xe6,0xab,0x7d,0xe4,0x26,0x0f,0xb6,0x37,0x3a,0x2f,0x62,0x97,0xa1,0xd1,0xf1,0x94,0x03,0x96,0xe9,0x7e,0xce,0x08,0x42,0xdb,0x3b,0x6d,0x33,0x91,0x41,0x23,0x16},
+    {0xf6,0x7f,0x26,0xf6,0xde,0x99,0xe4,0xb9,0x43,0x08,0x2c,0x74,0x7b,0xca,0x72,0x77,0xb1,0xf2,0xa4,0xe9,0x3f,0x15,0xa0,0x23,0x06,0x50,0xd0,0xd5,0xec,0xdf,0xdf,0x2c,0x40,0x86,0xf3,0x1f,0xd6,0x9c,0x49,0xdd,0xa0,0x25,0x36,0x06,0xc3,0x9b,0xcd,0x29,0xc3,0x3d,0xd7,0x3d,0x02,0xd8,0xe2,0x51,0x31,0x92,0x3b,0x20,0x7a,0x70,0x25,0x4a,0x6a,0xed,0xf6,0x53,0x8a,0x66,0xb7,0x2a,0xa1,0x70,0xd1,0x1d,0x58,0x42,0x42,0x30,0x61,0x01,0xe2,0x3a,0x4c,0x14,0x00,0x40,0xfc,0x49,0x8e,0x24,0x6d,0x89,0x21,0x57},
+    {0xae,0x1b,0x18,0xfd,0x17,0x55,0x6e,0x0b,0xb4,0x63,0xb9,0x2b,0x9f,0x62,0x22,0x90,0x25,0x46,0x06,0x32,0xe9,0xbc,0x09,0x55,0xda,0x13,0x3c,0xf6,0x74,0xdd,0x8e,0x57,0x4e,0xda,0xd0,0xa1,0x91,0x50,0x5d,0x28,0x08,0x3e,0xfe,0xb5,0xa7,0x6f,0xaa,0x4b,0xb3,0x93,0x93,0xe1,0x7c,0x17,0xe5,0x63,0xfd,0x30,0xb0,0xc4,0xaf,0x35,0xc9,0x03,0x3d,0x0c,0x2b,0x49,0xc6,0x76,0x72,0x99,0xfc,0x05,0xe2,0xdf,0xc4,0xc2,0xcc,0x47,0x3c,0x3a,0x62,0xdd,0x84,0x9b,0xd2,0xdc,0xa2,0xc7,0x88,0x02,0x59,0xab,0xc2,0x3e},
+    {0xb9,0x7b,0xd8,0xe4,0x7b,0xd2,0xa0,0xa1,0xed,0x1a,0x39,0x61,0xeb,0x4d,0x8b,0xa9,0x83,0x9b,0xcb,0x73,0xd0,0xdd,0xa0,0x99,0xce,0xca,0x0f,0x20,0x5a,0xc2,0xd5,0x2d,0xcb,0xd1,0x32,0xae,0x09,0x3a,0x21,0xa7,0xd5,0xc2,0xf5,0x40,0xdf,0x87,0x2b,0x0f,0x29,0xab,0x1e,0xe8,0xc6,0xa4,0xae,0x0b,0x5e,0xac,0xdb,0x6a,0x6c,0xf6,0x1b,0x0e,0x7e,0x88,0x2c,0x79,0xe9,0xd5,0xab,0xe2,0x5d,0x6d,0x92,0xcb,0x18,0x00,0x02,0x1a,0x1e,0x5f,0xae,0xba,0xcd,0x69,0xba,0xbf,0x5f,0x8f,0xe8,0x5a,0xb3,0x48,0x05,0x73},
+    {0xee,0xb8,0xa8,0xcb,0xa3,0x51,0x35,0xc4,0x16,0x5f,0x11,0xb2,0x1d,0x6f,0xa2,0x65,0x50,0x38,0x8c,0xab,0x52,0x4f,0x0f,0x76,0xca,0xb8,0x1d,0x41,0x3b,0x44,0x43,0x30,0x34,0xe3,0xd6,0xa1,0x4b,0x09,0x5b,0x80,0x19,0x3f,0x35,0x09,0x77,0xf1,0x3e,0xbf,0x2b,0x70,0x22,0x06,0xcb,0x06,0x3f,0x42,0xdd,0x45,0x78,0xd8,0x77,0x22,0x5a,0x58,0x62,0x89,0xd4,0x33,0x82,0x5f,0x8a,0xa1,0x7f,0x25,0x78,0xec,0xb5,0xc4,0x98,0x66,0xff,0x41,0x3e,0x37,0xa5,0x6f,0x8e,0xa7,0x1f,0x98,0xef,0x50,0x89,0x27,0x56,0x76},
+    {0xc0,0xc8,0x1f,0xd5,0x59,0xcf,0xc3,0x38,0xf2,0xb6,0x06,0x05,0xfd,0xd2,0xed,0x9b,0x8f,0x0e,0x57,0xab,0x9f,0x10,0xbf,0x26,0xa6,0x46,0xb8,0xc1,0xa8,0x60,0x41,0x3f,0x9d,0xcf,0x86,0xea,0xa3,0x73,0x70,0xe1,0xdc,0x5f,0x15,0x07,0xb7,0xfb,0x8c,0x3a,0x8e,0x8a,0x83,0x31,0xfc,0xe7,0x53,0x48,0x16,0xf6,0x13,0xb6,0x84,0xf4,0xbb,0x28,0x7c,0x6c,0x13,0x6f,0x5c,0x2f,0x61,0xf2,0xbe,0x11,0xdd,0xf6,0x07,0xd1,0xea,0xaf,0x33,0x6f,0xde,0x13,0xd2,0x9a,0x7e,0x52,0x5d,0xf7,0x88,0x81,0x35,0xcb,0x79,0x1e},
+    {0xf1,0xe3,0xf7,0xee,0xc3,0x36,0x34,0x01,0xf8,0x10,0x9e,0xfe,0x7f,0x6a,0x8b,0x82,0xfc,0xde,0xf9,0xbc,0xe5,0x08,0xf9,0x7f,0x31,0x38,0x3b,0x3a,0x1b,0x95,0xd7,0x65,0x81,0x81,0xe0,0xf5,0xd8,0x53,0xe9,0x77,0xd9,0xde,0x9d,0x29,0x44,0x0c,0xa5,0x84,0xe5,0x25,0x45,0x86,0x0c,0x2d,0x6c,0xdc,0xf4,0xf2,0xd1,0x39,0x2d,0xb5,0x8a,0x47,0x59,0xd1,0x52,0x92,0xd3,0xa4,0xa6,0x66,0x07,0xc8,0x1a,0x87,0xbc,0xe1,0xdd,0xe5,0x6f,0xc9,0xc1,0xa6,0x40,0x6b,0x2c,0xb8,0x14,0x22,0x21,0x1a,0x41,0x7a,0xd8,0x16},
+    {0x15,0x62,0x06,0x42,0x5a,0x7e,0xbd,0xb3,0xc1,0x24,0x5a,0x0c,0xcd,0xe3,0x9b,0x87,0xb7,0x94,0xf9,0xd6,0xb1,0x5d,0xc0,0x57,0xa6,0x8c,0xf3,0x65,0x81,0x7c,0xf8,0x28,0x83,0x05,0x4e,0xd5,0xe2,0xd5,0xa4,0xfb,0xfa,0x99,0xbd,0x2e,0xd7,0xaf,0x1f,0xe2,0x8f,0x77,0xe9,0x6e,0x73,0xc2,0x7a,0x49,0xde,0x6d,0x5a,0x7a,0x57,0x0b,0x99,0x1f,0xd6,0xf7,0xe8,0x1b,0xad,0x4e,0x34,0xa3,0x8f,0x79,0xea,0xac,0xeb,0x50,0x1e,0x7d,0x52,0xe0,0x0d,0x52,0x9e,0x56,0xc6,0x77,0x3e,0x6d,0x4d,0x53,0xe1,0x2f,0x88,0x45},
+    {0xd6,0x83,0x79,0x75,0x5d,0x34,0x69,0x66,0xa6,0x11,0xaa,0x17,0x11,0xed,0xb6,0x62,0x8f,0x12,0x5e,0x98,0x57,0x18,0xdd,0x7d,0xdd,0xf6,0x26,0xf6,0xb8,0xe5,0x8f,0x68,0xe4,0x6f,0x3c,0x94,0x29,0x99,0xac,0xd8,0xa2,0x92,0x83,0xa3,0x61,0xf1,0xf9,0xb5,0xf3,0x9a,0xc8,0xbe,0x13,0xdb,0x99,0x26,0x74,0xf0,0x05,0xe4,0x3c,0x84,0xcf,0x7d,0xc0,0x32,0x47,0x4a,0x48,0xd6,0x90,0x6c,0x99,0x32,0x56,0xca,0xfd,0x43,0x21,0xd5,0xe1,0xc6,0x5d,0x91,0xc3,0x28,0xbe,0xb3,0x1b,0x19,0x27,0x73,0x7e,0x68,0x39,0x67},
+    {0xa6,0x75,0x56,0x38,0x14,0x20,0x78,0xef,0xe8,0xa9,0xfd,0xaa,0x30,0x9f,0x64,0xa2,0xcb,0xa8,0xdf,0x5c,0x50,0xeb,0xd1,0x4c,0xb3,0xc0,0x4d,0x1d,0xba,0x5a,0x11,0x46,0xc0,0x1a,0x0c,0xc8,0x9d,0xcc,0x6d,0xa6,0x36,0xa4,0x38,0x1b,0xf4,0x5c,0xa0,0x97,0xc6,0xd7,0xdb,0x95,0xbe,0xf3,0xeb,0xa7,0xab,0x7d,0x7e,0x8d,0xf6,0xb8,0xa0,0x7d,0x76,0xda,0xb5,0xc3,0x53,0x19,0x0f,0xd4,0x9b,0x9e,0x11,0x21,0x73,0x6f,0xac,0x1d,0x60,0x59,0xb2,0xfe,0x21,0x60,0xcc,0x03,0x4b,0x4b,0x67,0x83,0x7e,0x88,0x5f,0x5a},
+    {0x11,0x3d,0xa1,0x70,0xcf,0x01,0x63,0x8f,0xc4,0xd0,0x0d,0x35,0x15,0xb8,0xce,0xcf,0x7e,0xa4,0xbc,0xa4,0xd4,0x97,0x02,0xf7,0x34,0x14,0x4d,0xe4,0x56,0xb6,0x69,0x36,0xb9,0x43,0xa6,0xa0,0xd3,0x28,0x96,0x9e,0x64,0x20,0xc3,0xe6,0x00,0xcb,0xc3,0xb5,0x32,0xec,0x2d,0x7c,0x89,0x02,0x53,0x9b,0x0c,0xc7,0xd1,0xd5,0xe2,0x7a,0xe3,0x43,0x33,0xe1,0xa6,0xed,0x06,0x3f,0x7e,0x38,0xc0,0x3a,0xa1,0x99,0x51,0x1d,0x30,0x67,0x11,0x38,0x26,0x36,0xf8,0xd8,0x5a,0xbd,0xbe,0xe9,0xd5,0x4f,0xcd,0xe6,0x21,0x6a},
+    {0x5f,0xe6,0x46,0x30,0x0a,0x17,0xc6,0xf1,0x24,0x35,0xd2,0x00,0x2a,0x2a,0x71,0x58,0x55,0xb7,0x82,0x8c,0x3c,0xbd,0xdb,0x69,0x57,0xff,0x95,0xa1,0xf1,0xf9,0x6b,0x58,0xe3,0xb2,0x99,0x66,0x12,0x29,0x41,0xef,0x01,0x13,0x8d,0x70,0x47,0x08,0xd3,0x71,0xbd,0xb0,0x82,0x11,0xd0,0x32,0x54,0x32,0x36,0x8b,0x1e,0x00,0x07,0x1b,0x37,0x45,0x0b,0x79,0xf8,0x5e,0x8d,0x08,0xdb,0xa6,0xe5,0x37,0x09,0x61,0xdc,0xf0,0x78,0x52,0xb8,0x6e,0xa1,0x61,0xd2,0x49,0x03,0xac,0x79,0x21,0xe5,0x90,0x37,0xb0,0xaf,0x0e},
+    {0x2f,0x04,0x48,0x37,0xc1,0x55,0x05,0x96,0x11,0xaa,0x0b,0x82,0xe6,0x41,0x9a,0x21,0x0c,0x6d,0x48,0x73,0x38,0xf7,0x81,0x1c,0x61,0xc6,0x02,0x5a,0x67,0xcc,0x9a,0x30,0x1d,0xae,0x75,0x0f,0x5e,0x80,0x40,0x51,0x30,0xcc,0x62,0x26,0xe3,0xfb,0x02,0xec,0x6d,0x39,0x92,0xea,0x1e,0xdf,0xeb,0x2c,0xb3,0x5b,0x43,0xc5,0x44,0x33,0xae,0x44,0xee,0x43,0xa5,0xbb,0xb9,0x89,0xf2,0x9c,0x42,0x71,0xc9,0x5a,0x9d,0x0e,0x76,0xf3,0xaa,0x60,0x93,0x4f,0xc6,0xe5,0x82,0x1d,0x8f,0x67,0x94,0x7f,0x1b,0x22,0xd5,0x62},
+    {0x6d,0x93,0xd0,0x18,0x9c,0x29,0x4c,0x52,0x0c,0x1a,0x0c,0x8a,0x6c,0xb5,0x6b,0xc8,0x31,0x86,0x4a,0xdb,0x2e,0x05,0x75,0xa3,0x62,0x45,0x75,0xbc,0xe4,0xfd,0x0e,0x5c,0x3c,0x7a,0xf7,0x3a,0x26,0xd4,0x85,0x75,0x4d,0x14,0xe9,0xfe,0x11,0x7b,0xae,0xdf,0x3d,0x19,0xf7,0x59,0x80,0x70,0x06,0xa5,0x37,0x20,0x92,0x83,0x53,0x9a,0xf2,0x14,0xf5,0xd7,0xb2,0x25,0xdc,0x7e,0x71,0xdf,0x40,0x30,0xb5,0x99,0xdb,0x70,0xf9,0x21,0x62,0x4c,0xed,0xc3,0xb7,0x34,0x92,0xda,0x3e,0x09,0xee,0x7b,0x5c,0x36,0x72,0x5e},
+    {0x7f,0x21,0x71,0x45,0x07,0xfc,0x5b,0x57,0x5b,0xd9,0x94,0x06,0x5d,0x67,0x79,0x37,0x33,0x1e,0x19,0xf4,0xbb,0x37,0x0a,0x9a,0xbc,0xea,0xb4,0x47,0x4c,0x10,0xf1,0x77,0x3e,0xb3,0x08,0x2f,0x06,0x39,0x93,0x7d,0xbe,0x32,0x9f,0xdf,0xe5,0x59,0x96,0x5b,0xfd,0xbd,0x9e,0x1f,0xad,0x3d,0xff,0xac,0xb7,0x49,0x73,0xcb,0x55,0x05,0xb2,0x70,0x4c,0x2c,0x11,0x55,0xc5,0x13,0x51,0xbe,0xcd,0x1f,0x88,0x9a,0x3a,0x42,0x88,0x66,0x47,0x3b,0x50,0x5e,0x85,0x77,0x66,0x44,0x4a,0x40,0x06,0x4a,0x8f,0x39,0x34,0x0e},
+    {0xe8,0xbd,0xce,0x3e,0xd9,0x22,0x7d,0xb6,0x07,0x2f,0x82,0x27,0x41,0xe8,0xb3,0x09,0x8d,0x6d,0x5b,0xb0,0x1f,0xa6,0x3f,0x74,0x72,0x23,0x36,0x8a,0x36,0x05,0x54,0x5e,0x28,0x19,0x4b,0x3e,0x09,0x0b,0x93,0x18,0x40,0xf6,0xf3,0x73,0x0e,0xe1,0xe3,0x7d,0x6f,0x5d,0x39,0x73,0xda,0x17,0x32,0xf4,0x3e,0x9c,0x37,0xca,0xd6,0xde,0x8a,0x6f,0x9a,0xb2,0xb7,0xfd,0x3d,0x12,0x40,0xe3,0x91,0xb2,0x1a,0xa2,0xe1,0x97,0x7b,0x48,0x9e,0x94,0xe6,0xfd,0x02,0x7d,0x96,0xf9,0x97,0xde,0xd3,0xc8,0x2e,0xe7,0x0d,0x78},
+    {0xbc,0xe7,0x9a,0x08,0x45,0x85,0xe2,0x0a,0x06,0x4d,0x7f,0x1c,0xcf,0xde,0x8d,0x38,0xb8,0x11,0x48,0x0a,0x51,0x15,0xac,0x38,0xe4,0x8c,0x92,0x71,0xf6,0x8b,0xb2,0x0e,0x72,0x27,0xf4,0x00,0xf3,0xea,0x1f,0x67,0xaa,0x41,0x8c,0x2a,0x2a,0xeb,0x72,0x8f,0x92,0x32,0x37,0x97,0xd7,0x7f,0xa1,0x29,0xa6,0x87,0xb5,0x32,0xad,0xc6,0xef,0x1d,0xa7,0x95,0x51,0xef,0x1a,0xbe,0x5b,0xaf,0xed,0x15,0x7b,0x91,0x77,0x12,0x8c,0x14,0x2e,0xda,0xe5,0x7a,0xfb,0xf7,0x91,0x29,0x67,0x28,0xdd,0xf8,0x1b,0x20,0x7d,0x46},
+    {0xad,0x4f,0xef,0x74,0x9a,0x91,0xfe,0x95,0xa2,0x08,0xa3,0xf6,0xec,0x7b,0x82,0x3a,0x01,0x7b,0xa4,0x09,0xd3,0x01,0x4e,0x96,0x97,0xc7,0xa3,0x5b,0x4f,0x3c,0xc4,0x71,0xa9,0xe7,0x7a,0x56,0xbd,0xf4,0x1e,0xbc,0xbd,0x98,0x44,0xd6,0xb2,0x4c,0x62,0x3f,0xc8,0x4e,0x1f,0x2c,0xd2,0x64,0x10,0xe4,0x01,0x40,0x38,0xba,0xa5,0xc5,0xf9,0x2e,0xcd,0x74,0x9e,0xfa,0xf6,0x6d,0xfd,0xb6,0x7a,0x26,0xaf,0xe4,0xbc,0x78,0x82,0xf1,0x0e,0x99,0xef,0xf1,0xd0,0xb3,0x55,0x82,0x93,0xf2,0xc5,0x90,0xa3,0x8c,0x75,0x5a},
+    {0x95,0x24,0x46,0xd9,0x10,0x27,0xb7,0xa2,0x03,0x50,0x7d,0xd5,0xd2,0xc6,0xa8,0x3a,0xca,0x87,0xb4,0xa0,0xbf,0x00,0xd4,0xe3,0xec,0x72,0xeb,0xb3,0x44,0xe2,0xba,0x2d,0x94,0xdc,0x61,0x1d,0x8b,0x91,0xe0,0x8c,0x66,0x30,0x81,0x9a,0x46,0x36,0xed,0x8d,0xd3,0xaa,0xe8,0xaf,0x29,0xa8,0xe6,0xd4,0x3f,0xd4,0x39,0xf6,0x27,0x80,0x73,0x0a,0xcc,0xe1,0xff,0x57,0x2f,0x4a,0x0f,0x98,0x43,0x98,0x83,0xe1,0x0d,0x0d,0x67,0x00,0xfd,0x15,0xfb,0x49,0x4a,0x3f,0x5c,0x10,0x9c,0xa6,0x26,0x51,0x63,0xca,0x98,0x26},
+    {0x78,0xba,0xb0,0x32,0x88,0x31,0x65,0xe7,0x8b,0xff,0x5c,0x92,0xf7,0x31,0x18,0x38,0xcc,0x1f,0x29,0xa0,0x91,0x1b,0xa8,0x08,0x07,0xeb,0xca,0x49,0xcc,0x3d,0xb4,0x1f,0x0e,0xd9,0x3d,0x5e,0x2f,0x70,0x3d,0x2e,0x86,0x53,0xd2,0xe4,0x18,0x09,0x3f,0x9e,0x6a,0xa9,0x4d,0x02,0xf6,0x3e,0x77,0x5e,0x32,0x33,0xfa,0x4a,0x0c,0x4b,0x00,0x3c,0x2b,0xb8,0xf4,0x06,0xac,0x46,0xa9,0x9a,0xf3,0xc4,0x06,0xa8,0xa5,0x84,0xa2,0x1c,0x87,0x47,0xcd,0xc6,0x5f,0x26,0xd3,0x3e,0x17,0xd2,0x1f,0xcd,0x01,0xfd,0x43,0x6b},
+    {0x44,0xc5,0x97,0x46,0x4b,0x5d,0xa7,0xc7,0xbf,0xff,0x0f,0xdf,0x48,0xf8,0xfd,0x15,0x5a,0x78,0x46,0xaa,0xeb,0xb9,0x68,0x28,0x14,0xf7,0x52,0x5b,0x10,0xd7,0x68,0x5a,0xf3,0x0e,0x76,0x3e,0x58,0x42,0xc7,0xb5,0x90,0xb9,0x0a,0xee,0xb9,0x52,0xdc,0x75,0x3f,0x92,0x2b,0x07,0xc2,0x27,0x14,0xbf,0xf0,0xd9,0xf0,0x6f,0x2d,0x0b,0x42,0x73,0x06,0x1e,0x85,0x9e,0xcb,0xf6,0x2c,0xaf,0xc4,0x38,0x22,0xc6,0x13,0x39,0x59,0x8f,0x73,0xf3,0xfb,0x99,0x96,0xb8,0x8a,0xda,0x9e,0xbc,0x34,0xea,0x2f,0x63,0xb5,0x3d},
+    {0xd8,0xd9,0x5d,0xf7,0x2b,0xee,0x6e,0xf4,0xa5,0x59,0x67,0x39,0xf6,0xb1,0x17,0x0d,0x73,0x72,0x9e,0x49,0x31,0xd1,0xf2,0x1b,0x13,0x5f,0xd7,0x49,0xdf,0x1a,0x32,0x04,0xd5,0x25,0x98,0x82,0xb1,0x90,0x49,0x2e,0x91,0x89,0x9a,0x3e,0x87,0xeb,0xea,0xed,0xf8,0x4a,0x70,0x4c,0x39,0x3d,0xf0,0xee,0x0e,0x2b,0xdf,0x95,0xa4,0x7e,0x19,0x59,0xae,0x5a,0xe5,0xe4,0x19,0x60,0xe1,0x04,0xe9,0x92,0x2f,0x7e,0x7a,0x43,0x7b,0xe7,0xa4,0x9a,0x15,0x6f,0xc1,0x2d,0xce,0xc7,0xc0,0x0c,0xd7,0xf4,0xc1,0xfd,0xea,0x45},
+    {0x2b,0xd7,0x45,0x80,0x85,0x01,0x84,0x69,0x51,0x06,0x2f,0xcf,0xa2,0xfa,0x22,0x4c,0xc6,0x2d,0x22,0x6b,0x65,0x36,0x1a,0x94,0xde,0xda,0x62,0x03,0xc8,0xeb,0x5e,0x5a,0xed,0xb1,0xcc,0xcf,0x24,0x46,0x0e,0xb6,0x95,0x03,0x5c,0xbd,0x92,0xc2,0xdb,0x59,0xc9,0x81,0x04,0xdc,0x1d,0x9d,0xa0,0x31,0x40,0xd9,0x56,0x5d,0xea,0xce,0x73,0x3f,0xc6,0x8d,0x4e,0x0a,0xd1,0xbf,0xa7,0xb7,0x39,0xb3,0xc9,0x44,0x7e,0x00,0x57,0xbe,0xfa,0xae,0x57,0x15,0x7f,0x20,0xc1,0x60,0xdb,0x18,0x62,0x26,0x91,0x88,0x05,0x26},
+    {0x04,0xff,0x60,0x83,0xa6,0x04,0xf7,0x59,0xf4,0xe6,0x61,0x76,0xde,0x3f,0xd9,0xc3,0x51,0x35,0x87,0x12,0x73,0x2a,0x1b,0x83,0x57,0x5d,0x61,0x4e,0x2e,0x0c,0xad,0x54,0x42,0xe5,0x76,0xc6,0x3c,0x8e,0x81,0x4c,0xad,0xcc,0xce,0x03,0x93,0x2c,0x42,0x5e,0x08,0x9f,0x12,0xb4,0xca,0xcc,0x07,0xec,0xb8,0x43,0x44,0xb2,0x10,0xfa,0xed,0x0d,0x2a,0x52,0x2b,0xb8,0xd5,0x67,0x3b,0xee,0xeb,0xc1,0xa5,0x9f,0x46,0x63,0xf1,0x36,0xd3,0x9f,0xc1,0x6e,0xf2,0xd2,0xb4,0xa5,0x08,0x94,0x7a,0xa7,0xba,0xb2,0xec,0x62},
+    {0x3d,0x2b,0x15,0x61,0x52,0x79,0xed,0xe5,0xd1,0xd7,0xdd,0x0e,0x7d,0x35,0x62,0x49,0x71,0x4c,0x6b,0xb9,0xd0,0xc8,0x82,0x74,0xbe,0xd8,0x66,0xa9,0x19,0xf9,0x59,0x2e,0x74,0x28,0xb6,0xaf,0x36,0x28,0x07,0x92,0xa5,0x04,0xe1,0x79,0x85,0x5e,0xcd,0x5f,0x4a,0xa1,0x30,0xc6,0xad,0x01,0xad,0x5a,0x98,0x3f,0x66,0x75,0x50,0x3d,0x91,0x61,0xda,0x31,0x32,0x1a,0x36,0x2d,0xc6,0x0d,0x70,0x02,0x20,0x94,0x32,0x58,0x47,0xfa,0xce,0x94,0x95,0x3f,0x51,0x01,0xd8,0x02,0x5c,0x5d,0xc0,0x31,0xa1,0xc2,0xdb,0x3d},
+    {0x4b,0xc5,0x5e,0xce,0xf9,0x0f,0xdc,0x9a,0x0d,0x13,0x2f,0x8c,0x6b,0x2a,0x9c,0x03,0x15,0x95,0xf8,0xf0,0xc7,0x07,0x80,0x02,0x6b,0xb3,0x04,0xac,0x14,0x83,0x96,0x78,0x14,0xbb,0x96,0x27,0xa2,0x57,0xaa,0xf3,0x21,0xda,0x07,0x9b,0xb7,0xba,0x3a,0x88,0x1c,0x39,0xa0,0x31,0x18,0xe2,0x4b,0xe5,0xf9,0x05,0x32,0xd8,0x38,0xfb,0xe7,0x5e,0x8e,0x6a,0x44,0x41,0xcb,0xfd,0x8d,0x53,0xf9,0x37,0x49,0x43,0xa9,0xfd,0xac,0xa5,0x78,0x8c,0x3c,0x26,0x8d,0x90,0xaf,0x46,0x09,0x0d,0xca,0x9b,0x3c,0x63,0xd0,0x61},
+    {0x66,0x25,0xdb,0xff,0x35,0x49,0x74,0x63,0xbb,0x68,0x0b,0x78,0x89,0x6b,0xbd,0xc5,0x03,0xec,0x3e,0x55,0x80,0x32,0x1b,0x6f,0xf5,0xd7,0xae,0x47,0xd8,0x5f,0x96,0x6e,0xdf,0x73,0xfc,0xf8,0xbc,0x28,0xa3,0xad,0xfc,0x37,0xf0,0xa6,0x5d,0x69,0x84,0xee,0x09,0xa9,0xc2,0x38,0xdb,0xb4,0x7f,0x63,0xdc,0x7b,0x06,0xf8,0x2d,0xac,0x23,0x5b,0x7b,0x52,0x80,0xee,0x53,0xb9,0xd2,0x9a,0x8d,0x6d,0xde,0xfa,0xaa,0x19,0x8f,0xe8,0xcf,0x82,0x0e,0x15,0x04,0x17,0x71,0x0e,0xdc,0xde,0x95,0xdd,0xb9,0xbb,0xb9,0x79},
+    {0xc2,0x26,0x31,0x6a,0x40,0x55,0xb3,0xeb,0x93,0xc3,0xc8,0x68,0xa8,0x83,0x63,0xd2,0x82,0x7a,0xb9,0xe5,0x29,0x64,0x0c,0x6c,0x47,0x21,0xfd,0xc9,0x58,0xf1,0x65,0x50,0x74,0x73,0x9f,0x8e,0xae,0x7d,0x99,0xd1,0x16,0x08,0xbb,0xcf,0xf8,0xa2,0x32,0xa0,0x0a,0x5f,0x44,0x6d,0x12,0xba,0x6c,0xcd,0x34,0xb8,0xcc,0x0a,0x46,0x11,0xa8,0x1b,0x54,0x99,0x42,0x0c,0xfb,0x69,0x81,0x70,0x67,0xcf,0x6e,0xd7,0xac,0x00,0x46,0xe1,0xba,0x45,0xe6,0x70,0x8a,0xb9,0xaa,0x2e,0xf2,0xfa,0xa4,0x58,0x9e,0xf3,0x81,0x39},
+    {0x93,0x0a,0x23,0x59,0x75,0x8a,0xfb,0x18,0x5d,0xf4,0xe6,0x60,0x69,0x8f,0x16,0x1d,0xb5,0x3c,0xa9,0x14,0x45,0xa9,0x85,0x3a,0xfd,0xd0,0xac,0x05,0x37,0x08,0xdc,0x38,0xde,0x6f,0xe6,0x6d,0xa5,0xdf,0x45,0xc8,0x3a,0x48,0x40,0x2c,0x00,0xa5,0x52,0xe1,0x32,0xf6,0xb4,0xc7,0x63,0xe1,0xd2,0xe9,0x65,0x1b,0xbc,0xdc,0x2e,0x45,0xf4,0x30,0x40,0x97,0x75,0xc5,0x82,0x27,0x6d,0x85,0xcc,0xbe,0x9c,0xf9,0x69,0x45,0x13,0xfa,0x71,0x4e,0xea,0xc0,0x73,0xfc,0x44,0x88,0x69,0x24,0x3f,0x59,0x1a,0x9a,0x2d,0x63},
+    {0xa6,0xcb,0x07,0xb8,0x15,0x6b,0xbb,0xf6,0xd7,0xf0,0x54,0xbc,0xdf,0xc7,0x23,0x18,0x0b,0x67,0x29,0x6e,0x03,0x97,0x1d,0xbb,0x57,0x4a,0xed,0x47,0x88,0xf4,0x24,0x0b,0xa7,0x84,0x0c,0xed,0x11,0xfd,0x09,0xbf,0x3a,0x69,0x9f,0x0d,0x81,0x71,0xf0,0x63,0x79,0x87,0xcf,0x57,0x2d,0x8c,0x90,0x21,0xa2,0x4b,0xf6,0x8a,0xf2,0x7d,0x5a,0x3a,0xc7,0xea,0x1b,0x51,0xbe,0xd4,0xda,0xdc,0xf2,0xcc,0x26,0xed,0x75,0x80,0x53,0xa4,0x65,0x9a,0x5f,0x00,0x9f,0xff,0x9c,0xe1,0x63,0x1f,0x48,0x75,0x44,0xf7,0xfc,0x34},
+    {0xca,0x67,0x97,0x78,0x4c,0xe0,0x97,0xc1,0x7d,0x46,0xd9,0x38,0xcb,0x4d,0x71,0xb8,0xa8,0x5f,0xf9,0x83,0x82,0x88,0xde,0x55,0xf7,0x63,0xfa,0x4d,0x16,0xdc,0x3b,0x3d,0x98,0xaa,0xcf,0x78,0xab,0x1d,0xbb,0xa5,0xf2,0x72,0x0b,0x19,0x67,0xa2,0xed,0x5c,0x8e,0x60,0x92,0x0a,0x11,0xc9,0x09,0x93,0xb0,0x74,0xb3,0x2f,0x04,0xa3,0x19,0x01,0x7d,0x17,0xc2,0xe8,0x9c,0xd8,0xa2,0x67,0xc1,0xd0,0x95,0x68,0xf6,0xa5,0x9d,0x66,0xb0,0xa2,0x82,0xb2,0xe5,0x98,0x65,0xf5,0x73,0x0a,0xe2,0xed,0xf1,0x88,0xc0,0x56},
+    {0x17,0x6e,0xa8,0x10,0x11,0x3d,0x6d,0x33,0xfa,0xb2,0x75,0x0b,0x32,0x88,0xf3,0xd7,0x88,0x29,0x07,0x25,0x76,0x33,0x15,0xf9,0x87,0x8b,0x10,0x99,0x6b,0x4c,0x67,0x09,0x02,0x8f,0xf3,0x24,0xac,0x5f,0x1b,0x58,0xbd,0x0c,0xe3,0xba,0xfe,0xe9,0x0b,0xa9,0xf0,0x92,0xcf,0x8a,0x02,0x69,0x21,0x9a,0x8f,0x03,0x59,0x83,0xa4,0x7e,0x8b,0x03,0xf8,0x6f,0x31,0x99,0x21,0xf8,0x4e,0x9f,0x4f,0x8d,0xa7,0xea,0x82,0xd2,0x49,0x2f,0x74,0x31,0xef,0x5a,0xab,0xa5,0x71,0x09,0x65,0xeb,0x69,0x59,0x02,0x31,0x5e,0x6e},
+    {0xfb,0x93,0xe5,0x87,0xf5,0x62,0x6c,0xb1,0x71,0x3e,0x5d,0xca,0xde,0xed,0x99,0x49,0x6d,0x3e,0xcc,0x14,0xe0,0xc1,0x91,0xb4,0xa8,0xdb,0xa8,0x89,0x47,0x11,0xf5,0x08,0x22,0x62,0x06,0x63,0x0e,0xfb,0x04,0x33,0x3f,0xba,0xac,0x87,0x89,0x06,0x35,0xfb,0xa3,0x61,0x10,0x8c,0x77,0x24,0x19,0xbd,0x20,0x86,0x83,0xd1,0x43,0xad,0x58,0x30,0xd0,0x63,0x76,0xe5,0xfd,0x0f,0x3c,0x32,0x10,0xa6,0x2e,0xa2,0x38,0xdf,0xc3,0x05,0x9a,0x4f,0x99,0xac,0xbd,0x8a,0xc7,0xbd,0x99,0xdc,0xe3,0xef,0xa4,0x9f,0x54,0x26},
+    {0xd6,0xf9,0x6b,0x1e,0x46,0x5a,0x1d,0x74,0x81,0xa5,0x77,0x77,0xfc,0xb3,0x05,0x23,0xd9,0xd3,0x74,0x64,0xa2,0x74,0x55,0xd4,0xff,0xe0,0x01,0x64,0xdc,0xe1,0x26,0x19,0x6e,0x66,0x3f,0xaf,0x49,0x85,0x46,0xdb,0xa5,0x0e,0x4a,0xf1,0x04,0xcf,0x7f,0xd7,0x47,0x0c,0xba,0xa4,0xf7,0x3f,0xf2,0x3d,0x85,0x3c,0xce,0x32,0xe1,0xdf,0x10,0x3a,0xa0,0xce,0x17,0xea,0x8a,0x4e,0x7f,0xe0,0xfd,0xc1,0x1f,0x3a,0x46,0x15,0xd5,0x2f,0xf1,0xc0,0xf2,0x31,0xfd,0x22,0x53,0x17,0x15,0x5d,0x1e,0x86,0x1d,0xd0,0xa1,0x1f},
+    {0x32,0x98,0x59,0x7d,0x94,0x55,0x80,0xcc,0x20,0x55,0xf1,0x37,0xda,0x56,0x46,0x1e,0x20,0x93,0x05,0x4e,0x74,0xf7,0xf6,0x99,0x33,0xcf,0x75,0x6a,0xbc,0x63,0x35,0x77,0xab,0x94,0xdf,0xd1,0x00,0xac,0xdc,0x38,0xe9,0x0d,0x08,0xd1,0xdd,0x2b,0x71,0x2e,0x62,0xe2,0xd5,0xfd,0x3e,0xe9,0x13,0x7f,0xe5,0x01,0x9a,0xee,0x18,0xed,0xfc,0x73,0xb3,0x9c,0x13,0x63,0x08,0xe9,0xb1,0x06,0xcd,0x3e,0xa0,0xc5,0x67,0xda,0x93,0xa4,0x32,0x89,0x63,0xad,0xc8,0xce,0x77,0x8d,0x44,0x4f,0x86,0x1b,0x70,0x6b,0x42,0x1f},
+    {0x01,0x1c,0x91,0x41,0x4c,0x26,0xc9,0xef,0x25,0x2c,0xa2,0x17,0xb8,0xb7,0xa3,0xf1,0x47,0x14,0x0f,0xf3,0x6b,0xda,0x75,0x58,0x90,0xb0,0x31,0x1d,0x27,0xf5,0x1a,0x4e,0x52,0x25,0xa1,0x91,0xc8,0x35,0x7e,0xf1,0x76,0x9c,0x5e,0x57,0x53,0x81,0x6b,0xb7,0x3e,0x72,0x9b,0x0d,0x6f,0x40,0x83,0xfa,0x38,0xe4,0xa7,0x3f,0x1b,0xbb,0x76,0x0b,0x9b,0x93,0x92,0x7f,0xf9,0xc1,0xb8,0x08,0x6e,0xab,0x44,0xd4,0xcb,0x71,0x67,0xbe,0x17,0x80,0xbb,0x99,0x63,0x64,0xe5,0x22,0x55,0xa9,0x72,0xb7,0x1e,0xd6,0x6d,0x7b},
+    {0x92,0x3d,0xf3,0x50,0xe8,0xc1,0xad,0xb7,0xcf,0xd5,0x8c,0x60,0x4f,0xfa,0x98,0x79,0xdb,0x5b,0xfc,0x8d,0xbd,0x2d,0x96,0xad,0x4f,0x2f,0x1d,0xaf,0xce,0x9b,0x3e,0x70,0xc7,0xd2,0x01,0xab,0xf9,0xab,0x30,0x57,0x18,0x3b,0x14,0x40,0xdc,0x76,0xfb,0x16,0x81,0xb2,0xcb,0xa0,0x65,0xbe,0x6c,0x86,0xfe,0x6a,0xff,0x9b,0x65,0x9b,0xfa,0x53,0x55,0x54,0x88,0x94,0xe9,0xc8,0x14,0x6c,0xe5,0xd4,0xae,0x65,0x66,0x5d,0x3a,0x84,0xf1,0x5a,0xd6,0xbc,0x3e,0xb7,0x1b,0x18,0x50,0x1f,0xc6,0xc4,0xe5,0x93,0x8d,0x39},
+    {0xf3,0x48,0xe2,0x33,0x67,0xd1,0x4b,0x1c,0x5f,0x0a,0xbf,0x15,0x87,0x12,0x9e,0xbd,0x76,0x03,0x0b,0xa1,0xf0,0x8c,0x3f,0xd4,0x13,0x1b,0x19,0xdf,0x5d,0x9b,0xb0,0x53,0xf2,0xe3,0xe7,0xd2,0x60,0x7c,0x87,0xc3,0xb1,0x8b,0x82,0x30,0xa0,0xaa,0x34,0x3b,0x38,0xf1,0x9e,0x73,0xe7,0x26,0x3e,0x28,0x77,0x05,0xc3,0x02,0x90,0x9c,0x9c,0x69,0xcc,0xf1,0x46,0x59,0x23,0xa7,0x06,0xf3,0x7d,0xd9,0xe5,0xcc,0xb5,0x18,0x17,0x92,0x75,0xe9,0xb4,0x81,0x47,0xd2,0xcd,0x28,0x07,0xd9,0xcd,0x6f,0x0c,0xf3,0xca,0x51},
+    {0x0a,0xe0,0x74,0x76,0x42,0xa7,0x0b,0xa6,0xf3,0x7b,0x7a,0xa1,0x70,0x85,0x0e,0x63,0xcc,0x24,0x33,0xcf,0x3d,0x56,0x58,0x37,0xaa,0xfd,0x83,0x23,0x29,0xaa,0x04,0x55,0xc7,0x54,0xac,0x18,0x9a,0xf9,0x7a,0x73,0x0f,0xb3,0x1c,0xc5,0xdc,0x78,0x33,0x90,0xc7,0x0c,0xe1,0x4c,0x33,0xbc,0x89,0x2b,0x9a,0xe9,0xf8,0x89,0xc1,0x29,0xae,0x12,0xcf,0x01,0x0d,0x1f,0xcb,0xc0,0x9e,0xa9,0xae,0xf7,0x34,0x3a,0xcc,0xef,0xd1,0x0d,0x22,0x4e,0x9c,0xd0,0x21,0x75,0xca,0x55,0xea,0xa5,0xeb,0x58,0xe9,0x4f,0xd1,0x5f},
+    {0x2c,0xab,0x45,0x28,0xdf,0x2d,0xdc,0xb5,0x93,0xe9,0x7f,0x0a,0xb1,0x91,0x94,0x06,0x46,0xe3,0x02,0x40,0xd6,0xf3,0xaa,0x4d,0xd1,0x74,0x64,0x58,0x6e,0xf2,0x3f,0x09,0x8e,0xcb,0x93,0xbf,0x5e,0xfe,0x42,0x3c,0x5f,0x56,0xd4,0x36,0x51,0xa8,0xdf,0xbe,0xe8,0x20,0x42,0x88,0x9e,0x85,0xf0,0xe0,0x28,0xd1,0x25,0x07,0x96,0x3f,0xd7,0x7d,0x29,0x98,0x05,0x68,0xfe,0x24,0x0d,0xb1,0xe5,0x23,0xaf,0xdb,0x72,0x06,0x73,0x75,0x29,0xac,0x57,0xb4,0x3a,0x25,0x67,0x13,0xa4,0x70,0xb4,0x86,0xbc,0xbc,0x59,0x2f},
+    {0x5f,0x13,0x17,0x99,0x42,0x7d,0x84,0x83,0xd7,0x03,0x7d,0x56,0x1f,0x91,0x1b,0xad,0xd1,0xaa,0x77,0xbe,0xd9,0x48,0x77,0x7e,0x4a,0xaf,0x51,0x2e,0x2e,0xb4,0x58,0x54,0x01,0xc3,0x91,0xb6,0x60,0xd5,0x41,0x70,0x1e,0xe7,0xd7,0xad,0x3f,0x1b,0x20,0x85,0x85,0x55,0x33,0x11,0x63,0xe1,0xc2,0x16,0xb1,0x28,0x08,0x01,0x3d,0x5e,0xa5,0x2a,0x4f,0x44,0x07,0x0c,0xe6,0x92,0x51,0xed,0x10,0x1d,0x42,0x74,0x2d,0x4e,0xc5,0x42,0x64,0xc8,0xb5,0xfd,0x82,0x4c,0x2b,0x35,0x64,0x86,0x76,0x8a,0x4a,0x00,0xe9,0x13},
+    {0xdb,0xce,0x2f,0x83,0x45,0x88,0x9d,0x73,0x63,0xf8,0x6b,0xae,0xc9,0xd6,0x38,0xfa,0xf7,0xfe,0x4f,0xb7,0xca,0x0d,0xbc,0x32,0x5e,0xe4,0xbc,0x14,0x88,0x7e,0x93,0x73,0x7f,0x87,0x3b,0x19,0xc9,0x00,0x2e,0xbb,0x6b,0x50,0xdc,0xe0,0x90,0xa8,0xe3,0xec,0x9f,0x64,0xde,0x36,0xc0,0xb7,0xf3,0xec,0x1a,0x9e,0xde,0x98,0x08,0x04,0x46,0x5f,0x8d,0xf4,0x7b,0x29,0x16,0x71,0x03,0xb9,0x34,0x68,0xf0,0xd4,0x22,0x3b,0xd1,0xa9,0xc6,0xbd,0x96,0x46,0x57,0x15,0x97,0xe1,0x35,0xe8,0xd5,0x91,0xe8,0xa4,0xf8,0x2c},
+    {0x67,0x0f,0x11,0x07,0x87,0xfd,0x93,0x6d,0x49,0xb5,0x38,0x7c,0xd3,0x09,0x4c,0xdd,0x86,0x6a,0x73,0xc2,0x4c,0x6a,0xb1,0x7c,0x09,0x2a,0x25,0x58,0x6e,0xbd,0x49,0x20,0xa2,0x6b,0xd0,0x17,0x7e,0x48,0xb5,0x2c,0x6b,0x19,0x50,0x39,0x1c,0x38,0xd2,0x24,0x30,0x8a,0x97,0x85,0x81,0x9c,0x65,0xd7,0xf6,0xa4,0xd6,0x91,0x28,0x7f,0x6f,0x7a,0x49,0xef,0x9a,0x6a,0x8d,0xfd,0x09,0x7d,0x0b,0xb9,0x3d,0x5b,0xbe,0x60,0xee,0xf0,0xd4,0xbf,0x9e,0x51,0x2c,0xb5,0x21,0x4c,0x1d,0x94,0x45,0xc5,0xdf,0xaa,0x11,0x60},
+    {0x3c,0xf8,0x95,0xcf,0x6d,0x92,0x67,0x5f,0x71,0x90,0x28,0x71,0x61,0x85,0x7e,0x7c,0x5b,0x7a,0x8f,0x99,0xf3,0xe7,0xa1,0xd6,0xe0,0xf9,0x62,0x0b,0x1b,0xcc,0xc5,0x6f,0x90,0xf8,0xcb,0x02,0xc8,0xd0,0xde,0x63,0xaa,0x6a,0xff,0x0d,0xca,0x98,0xd0,0xfb,0x99,0xed,0xb6,0xb9,0xfd,0x0a,0x4d,0x62,0x1e,0x0b,0x34,0x79,0xb7,0x18,0xce,0x69,0xcb,0x79,0x98,0xb2,0x28,0x55,0xef,0xd1,0x92,0x90,0x7e,0xd4,0x3c,0xae,0x1a,0xdd,0x52,0x23,0x9f,0x18,0x42,0x04,0x7e,0x12,0xf1,0x01,0x71,0xe5,0x3a,0x6b,0x59,0x15},
+    {0xa2,0x79,0x91,0x3f,0xd2,0x39,0x27,0x46,0xcf,0xdd,0xd6,0x97,0x31,0x12,0x83,0xff,0x8a,0x14,0xf2,0x53,0xb5,0xde,0x07,0x13,0xda,0x4d,0x5f,0x7b,0x68,0x37,0x22,0x0d,0xca,0x24,0x51,0x7e,0x16,0x31,0xff,0x09,0xdf,0x45,0xc7,0xd9,0x8b,0x15,0xe4,0x0b,0xe5,0x56,0xf5,0x7e,0x22,0x7d,0x2b,0x29,0x38,0xd1,0xb6,0xaf,0x41,0xe2,0xa4,0x3a,0xf5,0x05,0x33,0x2a,0xbf,0x38,0xc1,0x2c,0xc3,0x26,0xe9,0xa2,0x8f,0x3f,0x58,0x48,0xeb,0xd2,0x49,0x55,0xa2,0xb1,0x3a,0x08,0x6c,0xa3,0x87,0x46,0x6e,0xaa,0xfc,0x32},
+    {0xf5,0x9a,0x7d,0xc5,0x8d,0x6e,0xc5,0x7b,0xf2,0xbd,0xf0,0x9d,0xed,0xd2,0x0b,0x3e,0xa3,0xe4,0xef,0x22,0xde,0x14,0xc0,0xaa,0x5c,0x6a,0xbd,0xfe,0xce,0xe9,0x27,0x46,0xdf,0xcc,0x87,0x27,0x73,0xa4,0x07,0x32,0xf8,0xe3,0x13,0xf2,0x08,0x19,0xe3,0x17,0x4e,0x96,0x0d,0xf6,0xd7,0xec,0xb2,0xd5,0xe9,0x0b,0x60,0xc2,0x36,0x63,0x6f,0x74,0x1c,0x97,0x6c,0xab,0x45,0xf3,0x4a,0x3f,0x1f,0x73,0x43,0x99,0x72,0xeb,0x88,0xe2,0x6d,0x18,0x44,0x03,0x8a,0x6a,0x59,0x33,0x93,0x62,0xd6,0x7e,0x00,0x17,0x49,0x7b},
+    {0x64,0xb0,0x84,0xab,0x5c,0xfb,0x85,0x2d,0x14,0xbc,0xf3,0x89,0xd2,0x10,0x78,0x49,0x0c,0xce,0x15,0x7b,0x44,0xdc,0x6a,0x47,0x7b,0xfd,0x44,0xf8,0x76,0xa3,0x2b,0x12,0xdd,0xa2,0x53,0xdd,0x28,0x1b,0x34,0x54,0x3f,0xfc,0x42,0xdf,0x5b,0x90,0x17,0xaa,0xf4,0xf8,0xd2,0x4d,0xd9,0x92,0xf5,0x0f,0x7d,0xd3,0x8c,0xe0,0x0f,0x62,0x03,0x1d,0x54,0xe5,0xb4,0xa2,0xcd,0x32,0x02,0xc2,0x7f,0x18,0x5d,0x11,0x42,0xfd,0xd0,0x9e,0xd9,0x79,0xd4,0x7d,0xbe,0xb4,0xab,0x2e,0x4c,0xec,0x68,0x2b,0xf5,0x0b,0xc7,0x02},
+    {0xbb,0x2f,0x0b,0x5d,0x4b,0xec,0x87,0xa2,0xca,0x82,0x48,0x07,0x90,0x57,0x5c,0x41,0x5c,0x81,0xd0,0xc1,0x1e,0xa6,0x44,0xe0,0xe0,0xf5,0x9e,0x40,0x0a,0x4f,0x33,0x26,0xe1,0x72,0x8d,0x45,0xbf,0x32,0xe5,0xac,0xb5,0x3c,0xb7,0x7c,0xe0,0x68,0xe7,0x5b,0xe7,0xbd,0x8b,0xee,0x94,0x7d,0xcf,0x56,0x03,0x3a,0xb4,0xfe,0xe3,0x97,0x06,0x6b,0xc0,0xa3,0x62,0xdf,0x4a,0xf0,0xc8,0xb6,0x5d,0xa4,0x6d,0x07,0xef,0x00,0xf0,0x3e,0xa9,0xd2,0xf0,0x49,0x58,0xb9,0x9c,0x9c,0xae,0x2f,0x1b,0x44,0x43,0x7f,0xc3,0x1c},
+    {0x4f,0x32,0xc7,0x5c,0x5a,0x56,0x8f,0x50,0x22,0xa9,0x06,0xe5,0xc0,0xc4,0x61,0xd0,0x19,0xac,0x45,0x5c,0xdb,0xab,0x18,0xfb,0x4a,0x31,0x80,0x03,0xc1,0x09,0x68,0x6c,0xb9,0xae,0xce,0xc9,0xf1,0x56,0x66,0xd7,0x6a,0x65,0xe5,0x18,0xf8,0x15,0x5b,0x1c,0x34,0x23,0x4c,0x84,0x32,0x28,0xe7,0x26,0x38,0x68,0x19,0x2f,0x77,0x6f,0x34,0x3a,0xc8,0x6a,0xda,0xe2,0x12,0x51,0xd5,0xd2,0xed,0x51,0xe8,0xb1,0x31,0x03,0xbd,0xe9,0x62,0x72,0xc6,0x8e,0xdd,0x46,0x07,0x96,0xd0,0xc5,0xf7,0x6e,0x9f,0x1b,0x91,0x05},
+    {0xbb,0x0e,0xdf,0xf5,0x83,0x99,0x33,0xc1,0xac,0x4c,0x2c,0x51,0x8f,0x75,0xf3,0xc0,0xe1,0x98,0xb3,0x0b,0x0a,0x13,0xf1,0x2c,0x62,0x0c,0x27,0xaa,0xf9,0xec,0x3c,0x6b,0xef,0xea,0x2e,0x51,0xf3,0xac,0x49,0x53,0x49,0xcb,0xc1,0x1c,0xd3,0x41,0xc1,0x20,0x8d,0x68,0x9a,0xa9,0x07,0x0c,0x18,0x24,0x17,0x2d,0x4b,0xc6,0xd1,0xf9,0x5e,0x55,0x08,0xbd,0x73,0x3b,0xba,0x70,0xa7,0x36,0x0c,0xbf,0xaf,0xa3,0x08,0xef,0x4a,0x62,0xf2,0x46,0x09,0xb4,0x98,0xff,0x37,0x57,0x9d,0x74,0x81,0x33,0xe1,0x4d,0x5f,0x67},
+    {0xfc,0x82,0x17,0x6b,0x03,0x52,0x2c,0x0e,0xb4,0x83,0xad,0x6c,0x81,0x6c,0x81,0x64,0x3e,0x07,0x64,0x69,0xd9,0xbd,0xdc,0xd0,0x20,0xc5,0x64,0x01,0xf7,0x9d,0xd9,0x13,0x1d,0xb3,0xda,0x3b,0xd9,0xf6,0x2f,0xa1,0xfe,0x2d,0x65,0x9d,0x0f,0xd8,0x25,0x07,0x87,0x94,0xbe,0x9a,0xf3,0x4f,0x9c,0x01,0x43,0x3c,0xcd,0x82,0xb8,0x50,0xf4,0x60,0xca,0xc0,0xe5,0x21,0xc3,0x5e,0x4b,0x01,0xa2,0xbf,0x19,0xd7,0xc9,0x69,0xcb,0x4f,0xa0,0x23,0x00,0x75,0x18,0x1c,0x5f,0x4e,0x80,0xac,0xed,0x55,0x9e,0xde,0x06,0x1c},
+    {0xe2,0xc4,0x3e,0xa3,0xd6,0x7a,0x0f,0x99,0x8e,0xe0,0x2e,0xbe,0x38,0xf9,0x08,0x66,0x15,0x45,0x28,0x63,0xc5,0x43,0xa1,0x9c,0x0d,0xb6,0x2d,0xec,0x1f,0x8a,0xf3,0x4c,0xaa,0x69,0x6d,0xff,0x40,0x2b,0xd5,0xff,0xbb,0x49,0x40,0xdc,0x18,0x0b,0x53,0x34,0x97,0x98,0x4d,0xa3,0x2f,0x5c,0x4a,0x5e,0x2d,0xba,0x32,0x7d,0x8e,0x6f,0x09,0x78,0xe7,0x5c,0xfa,0x0d,0x65,0xaa,0xaa,0xa0,0x8c,0x47,0xb5,0x48,0x2a,0x9e,0xc4,0xf9,0x5b,0x72,0x03,0x70,0x7d,0xcc,0x09,0x4f,0xbe,0x1a,0x09,0x26,0x3a,0xad,0x3c,0x37},
+    {0x7c,0xf5,0xc9,0x82,0x4d,0x63,0x94,0xb2,0x36,0x45,0x93,0x24,0xe1,0xfd,0xcb,0x1f,0x5a,0xdb,0x8c,0x41,0xb3,0x4d,0x9c,0x9e,0xfc,0x19,0x44,0x45,0xd9,0xf3,0x40,0x00,0xad,0xbb,0xdd,0x89,0xfb,0xa8,0xbe,0xf1,0xcb,0xae,0xae,0x61,0xbc,0x2c,0xcb,0x3b,0x9d,0x8d,0x9b,0x1f,0xbb,0xa7,0x58,0x8f,0x86,0xa6,0x12,0x51,0xda,0x7e,0x54,0x21,0xd3,0x86,0x59,0xfd,0x39,0xe9,0xfd,0xde,0x0c,0x38,0x0a,0x51,0x89,0x2c,0x27,0xf4,0xb9,0x19,0x31,0xbb,0x07,0xa4,0x2b,0xb7,0xf4,0x4d,0x25,0x4a,0x33,0x0a,0x55,0x63},
+    {0x37,0xcf,0x69,0xb5,0xed,0xd6,0x07,0x65,0xe1,0x2e,0xa5,0x0c,0xb0,0x29,0x84,0x17,0x5d,0xd6,0x6b,0xeb,0x90,0x00,0x7c,0xea,0x51,0x8f,0xf7,0xda,0xc7,0x62,0xea,0x3e,0x49,0x7b,0x54,0x72,0x45,0x58,0xba,0x9b,0xe0,0x08,0xc4,0xe2,0xfa,0xc6,0x05,0xf3,0x8d,0xf1,0x34,0xc7,0x69,0xfa,0xe8,0x60,0x7a,0x76,0x7d,0xaa,0xaf,0x2b,0xa9,0x39,0x4e,0x27,0x93,0xe6,0x13,0xc7,0x24,0x9d,0x75,0xd3,0xdb,0x68,0x77,0x85,0x63,0x5f,0x9a,0xb3,0x8a,0xeb,0x60,0x55,0x52,0x70,0xcd,0xc4,0xc9,0x65,0x06,0x6a,0x43,0x68},
+    {0x27,0x3f,0x2f,0x20,0xe8,0x35,0x02,0xbc,0xb0,0x75,0xf9,0x64,0xe2,0x00,0x5c,0xc7,0x16,0x24,0x8c,0xa3,0xd5,0xe9,0xa4,0x91,0xf9,0x89,0xb7,0x8a,0xf6,0xe7,0xb6,0x17,0x7c,0x10,0x20,0xe8,0x17,0xd3,0x56,0x1e,0x65,0xe9,0x0a,0x84,0x44,0x68,0x26,0xc5,0x7a,0xfc,0x0f,0x32,0xc6,0xa1,0xe0,0xc1,0x72,0x14,0x61,0x91,0x9c,0x66,0x73,0x53,0x57,0x52,0x0e,0x9a,0xab,0x14,0x28,0x5d,0xfc,0xb3,0xca,0xc9,0x84,0x20,0x8f,0x90,0xca,0x1e,0x2d,0x5b,0x88,0xf5,0xca,0xaf,0x11,0x7d,0xf8,0x78,0xa6,0xb5,0xb4,0x1c},
+    {0x6c,0xfc,0x4a,0x39,0x6b,0xc0,0x64,0xb6,0xb1,0x5f,0xda,0x98,0x24,0xde,0x88,0x0c,0x34,0xd8,0xca,0x4b,0x16,0x03,0x8d,0x4f,0xa2,0x34,0x74,0xde,0x78,0xca,0x0b,0x33,0xe7,0x07,0xa0,0xa2,0x62,0xaa,0x74,0x6b,0xb1,0xc7,0x71,0xf0,0xb0,0xe0,0x11,0xf3,0x23,0xe2,0x0b,0x00,0x38,0xe4,0x07,0x57,0xac,0x6e,0xef,0x82,0x2d,0xfd,0xc0,0x2d,0x4e,0x74,0x19,0x11,0x84,0xff,0x2e,0x98,0x24,0x47,0x07,0x2b,0x96,0x5e,0x69,0xf9,0xfb,0x53,0xc9,0xbf,0x4f,0xc1,0x8a,0xc5,0xf5,0x1c,0x9f,0x36,0x1b,0xbe,0x31,0x3c},
+    {0xee,0x8a,0x94,0x08,0x4d,0x86,0xf4,0xb0,0x6f,0x1c,0xba,0x91,0xee,0x19,0xdc,0x07,0x58,0xa1,0xac,0xa6,0xae,0xcd,0x75,0x79,0xbb,0xd4,0x62,0x42,0x13,0x61,0x0b,0x33,0x72,0x42,0xcb,0xf9,0x93,0xbc,0x68,0xc1,0x98,0xdb,0xce,0xc7,0x1f,0x71,0xb8,0xae,0x7a,0x8d,0xac,0x34,0xaa,0x52,0x0e,0x7f,0xbb,0x55,0x7d,0x7e,0x09,0xc1,0xce,0x41,0x8a,0x80,0x6d,0xa2,0xd7,0x19,0x96,0xf7,0x6d,0x15,0x9e,0x1d,0x9e,0xd4,0x1f,0xbb,0x27,0xdf,0xa1,0xdb,0x6c,0xc3,0xd7,0x73,0x7d,0x77,0x28,0x1f,0xd9,0x4c,0xb4,0x26},
+    {0x75,0x74,0x38,0x8f,0x47,0x48,0xf0,0x51,0x3c,0xcb,0xbe,0x9c,0xf4,0xbc,0x5d,0xb2,0x55,0x20,0x9f,0xd9,0x44,0x12,0xab,0x9a,0xd6,0xa5,0x10,0x1c,0x6c,0x9e,0x70,0x2c,0x83,0x03,0x73,0x62,0x93,0xf2,0xb7,0xe1,0x2c,0x8a,0xca,0xeb,0xff,0x79,0x52,0x4b,0x14,0x13,0xd4,0xbf,0x8a,0x77,0xfc,0xda,0x0f,0x61,0x72,0x9c,0x14,0x10,0xeb,0x7d,0x7a,0xee,0x66,0x87,0x6a,0xaf,0x62,0xcb,0x0e,0xcd,0x53,0x55,0x04,0xec,0xcb,0x66,0xb5,0xe4,0x0b,0x0f,0x38,0x01,0x80,0x58,0xea,0xe2,0x2c,0xf6,0x9f,0x8e,0xe6,0x08},
+    {0xad,0x30,0xc1,0x4b,0x0a,0x50,0xad,0x34,0x9c,0xd4,0x0b,0x3d,0x49,0xdb,0x38,0x8d,0xbe,0x89,0x0a,0x50,0x98,0x3d,0x5c,0xa2,0x09,0x3b,0xba,0xee,0x87,0x3f,0x1f,0x2f,0xf9,0xf2,0xb8,0x0a,0xd5,0x09,0x2d,0x2f,0xdf,0x23,0x59,0xc5,0x8d,0x21,0xb9,0xac,0xb9,0x6c,0x76,0x73,0x26,0x34,0x8f,0x4a,0xf5,0x19,0xf7,0x38,0xd7,0x3b,0xb1,0x4c,0x4a,0xb6,0x15,0xe5,0x75,0x8c,0x84,0xf7,0x38,0x90,0x4a,0xdb,0xba,0x01,0x95,0xa5,0x50,0x1b,0x75,0x3f,0x3f,0x31,0x0d,0xc2,0xe8,0x2e,0xae,0xc0,0x53,0xe3,0xa1,0x19},
+    {0xc3,0x05,0xfa,0xba,0x60,0x75,0x1c,0x7d,0x61,0x5e,0xe5,0xc6,0xa0,0xa0,0xe1,0xb3,0x73,0x64,0xd6,0xc0,0x18,0x97,0x52,0xe3,0x86,0x34,0x0c,0xc2,0x11,0x6b,0x54,0x41,0xbd,0xbd,0x96,0xd5,0xcd,0x72,0x21,0xb4,0x40,0xfc,0xee,0x98,0x43,0x45,0xe0,0x93,0xb5,0x09,0x41,0xb4,0x47,0x53,0xb1,0x9f,0x34,0xae,0x66,0x02,0x99,0xd3,0x6b,0x73,0xb4,0xb3,0x34,0x93,0x50,0x2d,0x53,0x85,0x73,0x65,0x81,0x60,0x4b,0x11,0xfd,0x46,0x75,0x83,0x5c,0x42,0x30,0x5f,0x5f,0xcc,0x5c,0xab,0x7f,0xb8,0xa2,0x95,0x22,0x41},
+    {0xe9,0xd6,0x7e,0xf5,0x88,0x9b,0xc9,0x19,0x25,0xc8,0xf8,0x6d,0x26,0xcb,0x93,0x53,0x73,0xd2,0x0a,0xb3,0x13,0x32,0xee,0x5c,0x34,0x2e,0x2d,0xb5,0xeb,0x53,0xe1,0x14,0xc6,0xea,0x93,0xe2,0x61,0x52,0x65,0x2e,0xdb,0xac,0x33,0x21,0x03,0x92,0x5a,0x84,0x6b,0x99,0x00,0x79,0xcb,0x75,0x09,0x46,0x80,0xdd,0x5a,0x19,0x8d,0xbb,0x60,0x07,0x8a,0x81,0xe6,0xcd,0x17,0x1a,0x3e,0x41,0x84,0xa0,0x69,0xed,0xa9,0x6d,0x15,0x57,0xb1,0xcc,0xca,0x46,0x8f,0x26,0xbf,0x2c,0xf2,0xc5,0x3a,0xc3,0x9b,0xbe,0x34,0x6b},
+    {0xb2,0xc0,0x78,0x3a,0x64,0x2f,0xdf,0xf3,0x7c,0x02,0x2e,0xf2,0x1e,0x97,0x3e,0x4c,0xa3,0xb5,0xc1,0x49,0x5e,0x1c,0x7d,0xec,0x2d,0xdd,0x22,0x09,0x8f,0xc1,0x12,0x20,0xd3,0xf2,0x71,0x65,0x65,0x69,0xfc,0x11,0x7a,0x73,0x0e,0x53,0x45,0xe8,0xc9,0xc6,0x35,0x50,0xfe,0xd4,0xa2,0xe7,0x3a,0xe3,0x0b,0xd3,0x6d,0x2e,0xb6,0xc7,0xb9,0x01,0x29,0x9d,0xc8,0x5a,0xe5,0x55,0x0b,0x88,0x63,0xa7,0xa0,0x45,0x1f,0x24,0x83,0x14,0x1f,0x6c,0xe7,0xc2,0xdf,0xef,0x36,0x3d,0xe8,0xad,0x4b,0x4e,0x78,0x5b,0xaf,0x08},
+    {0x33,0x25,0x1f,0x88,0xdc,0x99,0x34,0x28,0xb6,0x23,0x93,0x77,0xda,0x25,0x05,0x9d,0xf4,0x41,0x34,0x67,0xfb,0xdd,0x7a,0x89,0x8d,0x16,0x3a,0x16,0x71,0x9d,0xb7,0x32,0x4b,0x2c,0xcc,0x89,0xd2,0x14,0x73,0xe2,0x8d,0x17,0x87,0xa2,0x11,0xbd,0xe4,0x4b,0xce,0x64,0x33,0xfa,0xd6,0x28,0xd5,0x18,0x6e,0x82,0xd9,0xaf,0xd5,0xc1,0x23,0x64,0x6a,0xb3,0xfc,0xed,0xd9,0xf8,0x85,0xcc,0xf9,0xe5,0x46,0x37,0x8f,0xc2,0xbc,0x22,0xcd,0xd3,0xe5,0xf9,0x38,0xe3,0x9d,0xe4,0xcc,0x2d,0x3e,0xc1,0xfb,0x5e,0x0a,0x48},
+    {0x71,0x20,0x62,0x01,0x0b,0xe7,0x51,0x0b,0xc5,0xaf,0x1d,0x8b,0xcf,0x05,0xb5,0x06,0xcd,0xab,0x5a,0xef,0x61,0xb0,0x6b,0x2c,0x31,0xbf,0xb7,0x0c,0x60,0x27,0xaa,0x47,0x1f,0x22,0xce,0x42,0xe4,0x4c,0x61,0xb6,0x28,0x39,0x05,0x4c,0xcc,0x9d,0x19,0x6e,0x03,0xbe,0x1c,0xdc,0xa4,0xb4,0x3f,0x66,0x06,0x8e,0x1c,0x69,0x47,0x1d,0xb3,0x24,0xc3,0xf8,0x15,0xc0,0xed,0x1e,0x54,0x2a,0x7c,0x3f,0x69,0x7c,0x7e,0xfe,0xa4,0x11,0xd6,0x78,0xa2,0x4e,0x13,0x66,0xaf,0xf0,0x94,0xa0,0xdd,0x14,0x5d,0x58,0x5b,0x54},
+    {0x0f,0x3a,0xd4,0xa0,0x5e,0x27,0xbf,0x67,0xbe,0xee,0x9b,0x08,0x34,0x8e,0xe6,0xad,0x2e,0xe7,0x79,0xd4,0x4c,0x13,0x89,0x42,0x54,0x54,0xba,0x32,0xc3,0xf9,0x62,0x0f,0xe1,0x21,0xb3,0xe3,0xd0,0xe4,0x04,0x62,0x95,0x1e,0xff,0x28,0x7a,0x63,0xaa,0x3b,0x9e,0xbd,0x99,0x5b,0xfd,0xcf,0x0c,0x0b,0x71,0xd0,0xc8,0x64,0x3e,0xdc,0x22,0x4d,0x39,0x5f,0x3b,0xd6,0x89,0x65,0xb4,0xfc,0x61,0xcf,0xcb,0x57,0x3f,0x6a,0xae,0x5c,0x05,0xfa,0x3a,0x95,0xd2,0xc2,0xba,0xfe,0x36,0x14,0x37,0x36,0x1a,0xa0,0x0f,0x1c},
+    {0xff,0x3d,0x94,0x22,0xb6,0x04,0xc6,0xd2,0xa0,0xb3,0xcf,0x44,0xce,0xbe,0x8c,0xbc,0x78,0x86,0x80,0x97,0xf3,0x4f,0x25,0x5d,0xbf,0xa6,0x1c,0x3b,0x4f,0x61,0xa3,0x0f,0x50,0x6a,0x93,0x8c,0x0e,0x2b,0x08,0x69,0xb6,0xc5,0xda,0xc1,0x35,0xa0,0xc9,0xf9,0x34,0xb6,0xdf,0xc4,0x54,0x3e,0xb7,0x6f,0x40,0xc1,0x2b,0x1d,0x9b,0x41,0x05,0x40,0xf0,0x82,0xbe,0xb9,0xbd,0xfe,0x03,0xa0,0x90,0xac,0x44,0x3a,0xaf,0xc1,0x89,0x20,0x8e,0xfa,0x54,0x19,0x91,0x9f,0x49,0xf8,0x42,0xab,0x40,0xef,0x8a,0x21,0xba,0x1f},
+    {0x3e,0xf5,0xc8,0xfa,0x48,0x94,0x54,0xab,0x41,0x37,0xa6,0x7b,0x9a,0xe8,0xf6,0x81,0x01,0x5e,0x2b,0x6c,0x7d,0x6c,0xfd,0x74,0x42,0x6e,0xc8,0xa8,0xca,0x3a,0x2e,0x39,0x94,0x01,0x7b,0x3e,0x04,0x57,0x3e,0x4f,0x7f,0xaf,0xda,0x08,0xee,0x3e,0x1d,0xa8,0xf1,0xde,0xdc,0x99,0xab,0xc6,0x39,0xc8,0xd5,0x61,0x77,0xff,0x13,0x5d,0x53,0x6c,0xaf,0x35,0x8a,0x3e,0xe9,0x34,0xbd,0x4c,0x16,0xe8,0x87,0x58,0x44,0x81,0x07,0x2e,0xab,0xb0,0x9a,0xf2,0x76,0x9c,0x31,0x19,0x3b,0xc1,0x0a,0xd5,0xe4,0x7f,0xe1,0x25},
+    {0x76,0xf6,0x04,0x1e,0xd7,0x9b,0x28,0x0a,0x95,0x0f,0x42,0xd6,0x52,0x1c,0x8e,0x20,0xab,0x1f,0x69,0x34,0xb0,0xd8,0x86,0x51,0x51,0xb3,0x9f,0x2a,0x44,0x51,0x57,0x25,0xa7,0x21,0xf1,0x76,0xf5,0x7f,0x5f,0x91,0xe3,0x87,0xcd,0x2f,0x27,0x32,0x4a,0xc3,0x26,0xe5,0x1b,0x4d,0xde,0x2f,0xba,0xcc,0x9b,0x89,0x69,0x89,0x8f,0x82,0xba,0x6b,0x01,0x39,0xfe,0x90,0x66,0xbc,0xd1,0xe2,0xd5,0x7a,0x99,0xa0,0x18,0x4a,0xb5,0x4c,0xd4,0x60,0x84,0xaf,0x14,0x69,0x1d,0x97,0xe4,0x7b,0x6b,0x7f,0x4f,0x50,0x9d,0x55},
+    {0xd5,0x54,0xeb,0xb3,0x78,0x83,0x73,0xa7,0x7c,0x3c,0x55,0xa5,0x66,0xd3,0x69,0x1d,0xba,0x00,0x28,0xf9,0x62,0xcf,0x26,0x0a,0x17,0x32,0x7e,0x80,0xd5,0x12,0xab,0x01,0xfd,0x66,0xd2,0xf6,0xe7,0x91,0x48,0x9c,0x1b,0x78,0x07,0x03,0x9b,0xa1,0x44,0x07,0x3b,0xe2,0x61,0x60,0x1d,0x8f,0x38,0x88,0x0e,0xd5,0x4b,0x35,0xa3,0xa6,0x3e,0x12,0x96,0x2d,0xe3,0x41,0x90,0x18,0x8d,0x11,0x48,0x58,0x31,0xd8,0xc2,0xe3,0xed,0xb9,0xd9,0x45,0x32,0xd8,0x71,0x42,0xab,0x1e,0x54,0xa1,0x18,0xc9,0xe2,0x61,0x39,0x4a},
+    {0xa0,0xbb,0xe6,0xf8,0xe0,0x3b,0xdc,0x71,0x0a,0xe3,0xff,0x7e,0x34,0xf8,0xce,0xd6,0x6a,0x47,0x3a,0xe1,0x5f,0x42,0x92,0xa9,0x63,0xb7,0x1d,0xfb,0xe3,0xbc,0xd6,0x2c,0x1e,0x3f,0x23,0xf3,0x44,0xd6,0x27,0x03,0x16,0xf0,0xfc,0x34,0x0e,0x26,0x9a,0x49,0x79,0xb9,0xda,0xf2,0x16,0xa7,0xb5,0x83,0x1f,0x11,0xd4,0x9b,0xad,0xee,0xac,0x68,0x10,0xc2,0xd7,0xf3,0x0e,0xc9,0xb4,0x38,0x0c,0x04,0xad,0xb7,0x24,0x6e,0x8e,0x30,0x23,0x3e,0xe7,0xb7,0xf1,0xd9,0x60,0x38,0x97,0xf5,0x08,0xb5,0xd5,0x60,0x57,0x59},
+    {0x97,0x63,0xaa,0x04,0xe1,0xbf,0x29,0x61,0xcb,0xfc,0xa7,0xa4,0x08,0x00,0x96,0x8f,0x58,0x94,0x90,0x7d,0x89,0xc0,0x8b,0x3f,0xa9,0x91,0xb2,0xdc,0x3e,0xa4,0x9f,0x70,0x90,0x27,0x02,0xfd,0xeb,0xcb,0x2a,0x88,0x60,0x57,0x11,0xc4,0x05,0x33,0xaf,0x89,0xf4,0x73,0x34,0x7d,0xe3,0x92,0xf4,0x65,0x2b,0x5a,0x51,0x54,0xdf,0xc5,0xb2,0x2c,0xca,0x2a,0xfd,0x63,0x8c,0x5d,0x0a,0xeb,0xff,0x4e,0x69,0x2e,0x66,0xc1,0x2b,0xd2,0x3a,0xb0,0xcb,0xf8,0x6e,0xf3,0x23,0x27,0x1f,0x13,0xc8,0xf0,0xec,0x29,0xf0,0x70},
+    {0x33,0x3e,0xed,0x2e,0xb3,0x07,0x13,0x46,0xe7,0x81,0x55,0xa4,0x33,0x2f,0x04,0xae,0x66,0x03,0x5f,0x19,0xd3,0x49,0x44,0xc9,0x58,0x48,0x31,0x6c,0x8a,0x5d,0x7d,0x0b,0xb9,0xb0,0x10,0x5e,0xaa,0xaf,0x6a,0x2a,0xa9,0x1a,0x04,0xef,0x70,0xa3,0xf0,0x78,0x1f,0xd6,0x3a,0xaa,0x77,0xfb,0x3e,0x77,0xe1,0xd9,0x4b,0xa7,0xa2,0xa5,0xec,0x44,0x43,0xd5,0x95,0x7b,0x32,0x48,0xd4,0x25,0x1d,0x0f,0x34,0xa3,0x00,0x83,0xd3,0x70,0x2b,0xc5,0xe1,0x60,0x1c,0x53,0x1c,0xde,0xe4,0xe9,0x7d,0x2c,0x51,0x24,0x22,0x27},
+    {0x2e,0x34,0xc5,0x49,0xaf,0x92,0xbc,0x1a,0xd0,0xfa,0xe6,0xb2,0x11,0xd8,0xee,0xff,0x29,0x4e,0xc8,0xfc,0x8d,0x8c,0xa2,0xef,0x43,0xc5,0x4c,0xa4,0x18,0xdf,0xb5,0x11,0xfc,0x75,0xa9,0x42,0x8a,0xbb,0x7b,0xbf,0x58,0xa3,0xad,0x96,0x77,0x39,0x5c,0x8c,0x48,0xaa,0xed,0xcd,0x6f,0xc7,0x7f,0xe2,0xa6,0x20,0xbc,0xf6,0xd7,0x5f,0x73,0x19,0x66,0x42,0xc8,0x42,0xd0,0x90,0xab,0xe3,0x7e,0x54,0x19,0x7f,0x0f,0x8e,0x84,0xeb,0xb9,0x97,0xa4,0x65,0xd0,0xa1,0x03,0x25,0x5f,0x89,0xdf,0x91,0x11,0x91,0xef,0x0f}
+};
+
+NAMESPACE_END  // Arch32
+NAMESPACE_END  // Donna
+NAMESPACE_END  // CryptoPP
+
+#endif  // CRYPTOPP_DOXYGEN_PROCESSING
+#endif  // CRYPTOPP_DONNA_32_H

+ 457 - 0
include/cryptlib/donna_64.h

@@ -0,0 +1,457 @@
+// donna_64.h - written and placed in public domain by Jeffrey Walton
+//              Crypto++ specific implementation wrapped around Andrew
+//              Moon's public domain curve25519-donna and ed25519-donna,
+//              https://github.com/floodyberry/curve25519-donna and
+//              https://github.com/floodyberry/ed25519-donna.
+
+// This source file multiplexes two different repos using namespaces. This
+// was a little easier from a project management standpoint. We only need
+// two files per architecture at the expense of namespaces and bloat.
+
+#ifndef CRYPTOPP_DONNA_64_H
+#define CRYPTOPP_DONNA_64_H
+#ifndef CRYPTOPP_DOXYGEN_PROCESSING
+
+#include "config.h"
+
+#if defined(CRYPTOPP_MSC_VERSION)
+# include <intrin.h>
+# pragma intrinsic(_umul128)
+# pragma intrinsic(__shiftright128)
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+NAMESPACE_BEGIN(Donna)
+NAMESPACE_BEGIN(Arch64)
+
+using CryptoPP::byte;
+using CryptoPP::word32;
+using CryptoPP::word64;
+
+// ******************** x25519 Agreement ************************* //
+
+#define ALIGN(n) CRYPTOPP_ALIGN_DATA(n)
+typedef word64 bignum25519[5];
+
+const byte basePoint[32] = {9};
+const word64 reduce_mask_40 = ((word64)1 << 40) - 1;
+const word64 reduce_mask_51 = ((word64)1 << 51) - 1;
+const word64 reduce_mask_52 = ((word64)1 << 52) - 1;
+const word64 reduce_mask_56 = ((word64)1 << 56) - 1;
+
+const word64 two54m152      = (((word64)1) << 54) - 152;
+const word64 two54m8        = (((word64)1) << 54) - 8;
+
+#if defined(CRYPTOPP_WORD128_AVAILABLE)
+using CryptoPP::word128;
+# define lo128(a) ((word64)a)
+# define hi128(a) ((word64)(a >> 64))
+# define add128(a,b) a += b;
+# define add128_64(a,b) a += (word64)b;
+# define mul64x64_128(out,a,b) out = (word128)a * b;
+# define shr128(out,in,shift) out = (word64)(in >> (shift));
+# define shl128(out,in,shift) out = (word64)((in << shift) >> 64);
+
+#elif defined(CRYPTOPP_MSC_VERSION)
+struct word128 { word64 lo, hi; };
+# define mul64x64_128(out,a,b) out.lo = _umul128(a,b,&out.hi);
+# define shr128_pair(out,hi,lo,shift) out = __shiftright128(lo, hi, shift);
+# define shl128_pair(out,hi,lo,shift) out = __shiftleft128(lo, hi, shift);
+# define shr128(out,in,shift) shr128_pair(out, in.hi, in.lo, shift)
+# define shl128(out,in,shift) shl128_pair(out, in.hi, in.lo, shift)
+# define add128(a,b) { word64 p = a.lo; a.lo += b.lo; a.hi += b.hi + (a.lo < p); }
+# define add128_64(a,b) { word64 p = a.lo; a.lo += b; a.hi += (a.lo < p); }
+# define lo128(a) (a.lo)
+# define hi128(a) (a.hi)
+
+#elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
+struct word128 { word64 lo, hi; };
+# define mul64x64_128(out,a,b) __asm__ ("mulq %3" : "=a" (out.lo), "=d" (out.hi) : "a" (a), "rm" (b));
+# define shr128_pair(out,hi,lo,shift) __asm__ ("shrdq %2,%1,%0" : "+r" (lo) : "r" (hi), "J" (shift)); out = lo;
+# define shl128_pair(out,hi,lo,shift) __asm__ ("shldq %2,%1,%0" : "+r" (hi) : "r" (lo), "J" (shift)); out = hi;
+# define shr128(out,in,shift) shr128_pair(out,in.hi, in.lo, shift)
+# define shl128(out,in,shift) shl128_pair(out,in.hi, in.lo, shift)
+# define add128(a,b) __asm__ ("addq %4,%2; adcq %5,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b.lo), "rm" (b.hi) : "cc");
+# define add128_64(a,b) __asm__ ("addq %4,%2; adcq $0,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b) : "cc");
+# define lo128(a) (a.lo)
+# define hi128(a) (a.hi)
+
+#else
+// https://groups.google.com/forum/#!forum/cryptopp-users
+# error "Unsupported platform"
+#endif
+
+// ****************** ed25519 Signatures *********************** //
+
+typedef byte hash_512bits[64];
+
+const int bignum256modm_bits_per_limb = 56;
+const int bignum256modm_limb_size = 5;
+typedef word64 bignum256modm_element_t;
+typedef bignum256modm_element_t bignum256modm[5];
+
+/* multiples of p */
+const word64 twoP0      = 0x0fffffffffffda;
+const word64 twoP1234   = 0x0ffffffffffffe;
+const word64 fourP0     = 0x1fffffffffffb4;
+const word64 fourP1234  = 0x1ffffffffffffc;
+
+struct ge25519 {
+    bignum25519 x, y, z, t;
+};
+
+struct ge25519_p1p1 {
+    bignum25519 x, y, z, t;
+};
+
+struct ge25519_niels {
+    bignum25519 ysubx, xaddy, t2d;
+};
+
+struct ge25519_pniels {
+    bignum25519 ysubx, xaddy, z, t2d;
+};
+
+#define S1_SWINDOWSIZE 5
+#define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2))
+#define S2_SWINDOWSIZE 7
+#define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2))
+
+// *************** ed25519-donna-64bit-tables.h *************** //
+
+const ge25519 ge25519_basepoint = {
+    {0x00062d608f25d51a,0x000412a4b4f6592a,0x00075b7171a4b31d,0x0001ff60527118fe,0x000216936d3cd6e5},
+    {0x0006666666666658,0x0004cccccccccccc,0x0001999999999999,0x0003333333333333,0x0006666666666666},
+    {0x0000000000000001,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000},
+    {0x00068ab3a5b7dda3,0x00000eea2a5eadbb,0x0002af8df483c27e,0x000332b375274732,0x00067875f0fd78b7}
+};
+
+const bignum25519 ge25519_ecd = {
+    0x00034dca135978a3,0x0001a8283b156ebd,0x0005e7a26001c029,0x000739c663a03cbb,0x00052036cee2b6ff
+};
+
+const bignum25519 ge25519_ec2d = {
+    0x00069b9426b2f159,0x00035050762add7a,0x0003cf44c0038052,0x0006738cc7407977,0x0002406d9dc56dff
+};
+
+const bignum25519 ge25519_sqrtneg1 = {
+    0x00061b274a0ea0b0,0x0000d5a5fc8f189d,0x0007ef5e9cbd0c60,0x00078595a6804c9e,0x0002b8324804fc1d
+};
+
+const ge25519_niels ge25519_niels_sliding_multiples[32] = {
+    {{0x00003905d740913e,0x0000ba2817d673a2,0x00023e2827f4e67c,0x000133d2e0c21a34,0x00044fd2f9298f81},{0x000493c6f58c3b85,0x0000df7181c325f7,0x0000f50b0b3e4cb7,0x0005329385a44c32,0x00007cf9d3a33d4b},{0x00011205877aaa68,0x000479955893d579,0x00050d66309b67a0,0x0002d42d0dbee5ee,0x0006f117b689f0c6}},
+    {{0x00011fe8a4fcd265,0x0007bcb8374faacc,0x00052f5af4ef4d4f,0x0005314098f98d10,0x0002ab91587555bd},{0x0005b0a84cee9730,0x00061d10c97155e4,0x0004059cc8096a10,0x00047a608da8014f,0x0007a164e1b9a80f},{0x0006933f0dd0d889,0x00044386bb4c4295,0x0003cb6d3162508c,0x00026368b872a2c6,0x0005a2826af12b9b}},
+    {{0x000182c3a447d6ba,0x00022964e536eff2,0x000192821f540053,0x0002f9f19e788e5c,0x000154a7e73eb1b5},{0x0002bc4408a5bb33,0x000078ebdda05442,0x0002ffb112354123,0x000375ee8df5862d,0x0002945ccf146e20},{0x0003dbf1812a8285,0x0000fa17ba3f9797,0x0006f69cb49c3820,0x00034d5a0db3858d,0x00043aabe696b3bb}},
+    {{0x00072c9aaa3221b1,0x000267774474f74d,0x000064b0e9b28085,0x0003f04ef53b27c9,0x0001d6edd5d2e531},{0x00025cd0944ea3bf,0x00075673b81a4d63,0x000150b925d1c0d4,0x00013f38d9294114,0x000461bea69283c9},{0x00036dc801b8b3a2,0x0000e0a7d4935e30,0x0001deb7cecc0d7d,0x000053a94e20dd2c,0x0007a9fbb1c6a0f9}},
+    {{0x0006217e039d8064,0x0006dea408337e6d,0x00057ac112628206,0x000647cb65e30473,0x00049c05a51fadc9},{0x0006678aa6a8632f,0x0005ea3788d8b365,0x00021bd6d6994279,0x0007ace75919e4e3,0x00034b9ed338add7},{0x0004e8bf9045af1b,0x000514e33a45e0d6,0x0007533c5b8bfe0f,0x000583557b7e14c9,0x00073c172021b008}},
+    {{0x00075b0249864348,0x00052ee11070262b,0x000237ae54fb5acd,0x0003bfd1d03aaab5,0x00018ab598029d5c},{0x000700848a802ade,0x0001e04605c4e5f7,0x0005c0d01b9767fb,0x0007d7889f42388b,0x0004275aae2546d8},{0x00032cc5fd6089e9,0x000426505c949b05,0x00046a18880c7ad2,0x0004a4221888ccda,0x0003dc65522b53df}},
+    {{0x0007013b327fbf93,0x0001336eeded6a0d,0x0002b565a2bbf3af,0x000253ce89591955,0x0000267882d17602},{0x0000c222a2007f6d,0x000356b79bdb77ee,0x00041ee81efe12ce,0x000120a9bd07097d,0x000234fd7eec346f},{0x0000a119732ea378,0x00063bf1ba8e2a6c,0x00069f94cc90df9a,0x000431d1779bfc48,0x000497ba6fdaa097}},
+    {{0x0003cd86468ccf0b,0x00048553221ac081,0x0006c9464b4e0a6e,0x00075fba84180403,0x00043b5cd4218d05},{0x0006cc0313cfeaa0,0x0001a313848da499,0x0007cb534219230a,0x00039596dedefd60,0x00061e22917f12de},{0x0002762f9bd0b516,0x0001c6e7fbddcbb3,0x00075909c3ace2bd,0x00042101972d3ec9,0x000511d61210ae4d}},
+    {{0x000386484420de87,0x0002d6b25db68102,0x000650b4962873c0,0x0004081cfd271394,0x00071a7fe6fe2482},{0x000676ef950e9d81,0x0001b81ae089f258,0x00063c4922951883,0x0002f1d54d9b3237,0x0006d325924ddb85},{0x000182b8a5c8c854,0x00073fcbe5406d8e,0x0005de3430cff451,0x000554b967ac8c41,0x0004746c4b6559ee}},
+    {{0x000546c864741147,0x0003a1df99092690,0x0001ca8cc9f4d6bb,0x00036b7fc9cd3b03,0x000219663497db5e},{0x00077b3c6dc69a2b,0x0004edf13ec2fa6e,0x0004e85ad77beac8,0x0007dba2b28e7bda,0x0005c9a51de34fe9},{0x0000f1cf79f10e67,0x00043ccb0a2b7ea2,0x00005089dfff776a,0x0001dd84e1d38b88,0x0004804503c60822}},
+    {{0x000021d23a36d175,0x0004fd3373c6476d,0x00020e291eeed02a,0x00062f2ecf2e7210,0x000771e098858de4},{0x00049ed02ca37fc7,0x000474c2b5957884,0x0005b8388e816683,0x0004b6c454b76be4,0x000553398a516506},{0x0002f5d278451edf,0x000730b133997342,0x0006965420eb6975,0x000308a3bfa516cf,0x0005a5ed1d68ff5a}},
+    {{0x0005e0c558527359,0x0003395b73afd75c,0x000072afa4e4b970,0x00062214329e0f6d,0x000019b60135fefd},{0x0005122afe150e83,0x0004afc966bb0232,0x0001c478833c8268,0x00017839c3fc148f,0x00044acb897d8bf9},{0x000068145e134b83,0x0001e4860982c3cc,0x000068fb5f13d799,0x0007c9283744547e,0x000150c49fde6ad2}},
+    {{0x0001863c9cdca868,0x0003770e295a1709,0x0000d85a3720fd13,0x0005e0ff1f71ab06,0x00078a6d7791e05f},{0x0003f29509471138,0x000729eeb4ca31cf,0x00069c22b575bfbc,0x0004910857bce212,0x0006b2b5a075bb99},{0x0007704b47a0b976,0x0002ae82e91aab17,0x00050bd6429806cd,0x00068055158fd8ea,0x000725c7ffc4ad55}},
+    {{0x00002bf71cd098c0,0x00049dabcc6cd230,0x00040a6533f905b2,0x000573efac2eb8a4,0x0004cd54625f855f},{0x00026715d1cf99b2,0x0002205441a69c88,0x000448427dcd4b54,0x0001d191e88abdc5,0x000794cc9277cb1f},{0x0006c426c2ac5053,0x0005a65ece4b095e,0x0000c44086f26bb6,0x0007429568197885,0x0007008357b6fcc8}},
+    {{0x00039fbb82584a34,0x00047a568f257a03,0x00014d88091ead91,0x0002145b18b1ce24,0x00013a92a3669d6d},{0x0000672738773f01,0x000752bf799f6171,0x0006b4a6dae33323,0x0007b54696ead1dc,0x00006ef7e9851ad0},{0x0003771cc0577de5,0x0003ca06bb8b9952,0x00000b81c5d50390,0x00043512340780ec,0x0003c296ddf8a2af}},
+    {{0x00034d2ebb1f2541,0x0000e815b723ff9d,0x000286b416e25443,0x0000bdfe38d1bee8,0x0000a892c7007477},{0x000515f9d914a713,0x00073191ff2255d5,0x00054f5cc2a4bdef,0x0003dd57fc118bcf,0x0007a99d393490c7},{0x0002ed2436bda3e8,0x00002afd00f291ea,0x0000be7381dea321,0x0003e952d4b2b193,0x000286762d28302f}},
+    {{0x00058e2bce2ef5bd,0x00068ce8f78c6f8a,0x0006ee26e39261b2,0x00033d0aa50bcf9d,0x0007686f2a3d6f17},{0x000036093ce35b25,0x0003b64d7552e9cf,0x00071ee0fe0b8460,0x00069d0660c969e5,0x00032f1da046a9d9},{0x000512a66d597c6a,0x0000609a70a57551,0x000026c08a3c464c,0x0004531fc8ee39e1,0x000561305f8a9ad2}},
+    {{0x0002cc28e7b0c0d5,0x00077b60eb8a6ce4,0x0004042985c277a6,0x000636657b46d3eb,0x000030a1aef2c57c},{0x0004978dec92aed1,0x000069adae7ca201,0x00011ee923290f55,0x00069641898d916c,0x00000aaec53e35d4},{0x0001f773003ad2aa,0x000005642cc10f76,0x00003b48f82cfca6,0x0002403c10ee4329,0x00020be9c1c24065}},
+    {{0x0000e44ae2025e60,0x0005f97b9727041c,0x0005683472c0ecec,0x000188882eb1ce7c,0x00069764c545067e},{0x000387d8249673a6,0x0005bea8dc927c2a,0x0005bd8ed5650ef0,0x0000ef0e3fcd40e1,0x000750ab3361f0ac},{0x00023283a2f81037,0x000477aff97e23d1,0x0000b8958dbcbb68,0x0000205b97e8add6,0x00054f96b3fb7075}},
+    {{0x0005afc616b11ecd,0x00039f4aec8f22ef,0x0003b39e1625d92e,0x0005f85bd4508873,0x00078e6839fbe85d},{0x0005f20429669279,0x00008fafae4941f5,0x00015d83c4eb7688,0x0001cf379eca4146,0x0003d7fe9c52bb75},{0x00032df737b8856b,0x0000608342f14e06,0x0003967889d74175,0x0001211907fba550,0x00070f268f350088}},
+    {{0x0004112070dcf355,0x0007dcff9c22e464,0x00054ada60e03325,0x00025cd98eef769a,0x000404e56c039b8c},{0x00064583b1805f47,0x00022c1baf832cd0,0x000132c01bd4d717,0x0004ecf4c3a75b8f,0x0007c0d345cfad88},{0x00071f4b8c78338a,0x00062cfc16bc2b23,0x00017cf51280d9aa,0x0003bbae5e20a95a,0x00020d754762aaec}},
+    {{0x0004feb135b9f543,0x00063bd192ad93ae,0x00044e2ea612cdf7,0x000670f4991583ab,0x00038b8ada8790b4},{0x0007c36fc73bb758,0x0004a6c797734bd1,0x0000ef248ab3950e,0x00063154c9a53ec8,0x0002b8f1e46f3cee},{0x00004a9cdf51f95d,0x0005d963fbd596b8,0x00022d9b68ace54a,0x0004a98e8836c599,0x000049aeb32ceba1}},
+    {{0x00067d3c63dcfe7e,0x000112f0adc81aee,0x00053df04c827165,0x0002fe5b33b430f0,0x00051c665e0c8d62},{0x00007d0b75fc7931,0x00016f4ce4ba754a,0x0005ace4c03fbe49,0x00027e0ec12a159c,0x000795ee17530f67},{0x00025b0a52ecbd81,0x0005dc0695fce4a9,0x0003b928c575047d,0x00023bf3512686e5,0x0006cd19bf49dc54}},
+    {{0x0007619052179ca3,0x0000c16593f0afd0,0x000265c4795c7428,0x00031c40515d5442,0x0007520f3db40b2e},{0x0006612165afc386,0x0001171aa36203ff,0x0002642ea820a8aa,0x0001f3bb7b313f10,0x0005e01b3a7429e4},{0x00050be3d39357a1,0x0003ab33d294a7b6,0x0004c479ba59edb3,0x0004c30d184d326f,0x00071092c9ccef3c}},
+    {{0x0000523f0364918c,0x000687f56d638a7b,0x00020796928ad013,0x0005d38405a54f33,0x0000ea15b03d0257},{0x0003d8ac74051dcf,0x00010ab6f543d0ad,0x0005d0f3ac0fda90,0x0005ef1d2573e5e4,0x0004173a5bb7137a},{0x00056e31f0f9218a,0x0005635f88e102f8,0x0002cbc5d969a5b8,0x000533fbc98b347a,0x0005fc565614a4e3}},
+    {{0x0006570dc46d7ae5,0x00018a9f1b91e26d,0x000436b6183f42ab,0x000550acaa4f8198,0x00062711c414c454},{0x0002e1e67790988e,0x0001e38b9ae44912,0x000648fbb4075654,0x00028df1d840cd72,0x0003214c7409d466},{0x0001827406651770,0x0004d144f286c265,0x00017488f0ee9281,0x00019e6cdb5c760c,0x0005bea94073ecb8}},
+    {{0x0005bf0912c89be4,0x00062fadcaf38c83,0x00025ec196b3ce2c,0x00077655ff4f017b,0x0003aacd5c148f61},{0x0000ce63f343d2f8,0x0001e0a87d1e368e,0x000045edbc019eea,0x0006979aed28d0d1,0x0004ad0785944f1b},{0x00063b34c3318301,0x0000e0e62d04d0b1,0x000676a233726701,0x00029e9a042d9769,0x0003aff0cb1d9028}},
+    {{0x0005c7eb3a20405e,0x0005fdb5aad930f8,0x0004a757e63b8c47,0x00028e9492972456,0x000110e7e86f4cd2},{0x0006430bf4c53505,0x000264c3e4507244,0x00074c9f19a39270,0x00073f84f799bc47,0x0002ccf9f732bd99},{0x0000d89ed603f5e4,0x00051e1604018af8,0x0000b8eedc4a2218,0x00051ba98b9384d0,0x00005c557e0b9693}},
+    {{0x0001ce311fc97e6f,0x0006023f3fb5db1f,0x0007b49775e8fc98,0x0003ad70adbf5045,0x0006e154c178fe98},{0x0006bbb089c20eb0,0x0006df41fb0b9eee,0x00051087ed87e16f,0x000102db5c9fa731,0x000289fef0841861},{0x00016336fed69abf,0x0004f066b929f9ec,0x0004e9ff9e6c5b93,0x00018c89bc4bb2ba,0x0006afbf642a95ca}},
+    {{0x0000de0c62f5d2c1,0x00049601cf734fb5,0x0006b5c38263f0f6,0x0004623ef5b56d06,0x0000db4b851b9503},{0x00055070f913a8cc,0x000765619eac2bbc,0x0003ab5225f47459,0x00076ced14ab5b48,0x00012c093cedb801},{0x00047f9308b8190f,0x000414235c621f82,0x00031f5ff41a5a76,0x0006736773aab96d,0x00033aa8799c6635}},
+    {{0x0007f51ebd085cf2,0x00012cfa67e3f5e1,0x0001800cf1e3d46a,0x00054337615ff0a8,0x000233c6f29e8e21},{0x0000f588fc156cb1,0x000363414da4f069,0x0007296ad9b68aea,0x0004d3711316ae43,0x000212cd0c1c8d58},{0x0004d5107f18c781,0x00064a4fd3a51a5e,0x0004f4cd0448bb37,0x000671d38543151e,0x0001db7778911914}},
+    {{0x000352397c6bc26f,0x00018a7aa0227bbe,0x0005e68cc1ea5f8b,0x0006fe3e3a7a1d5f,0x00031ad97ad26e2a},{0x00014769dd701ab6,0x00028339f1b4b667,0x0004ab214b8ae37b,0x00025f0aefa0b0fe,0x0007ae2ca8a017d2},{0x000017ed0920b962,0x000187e33b53b6fd,0x00055829907a1463,0x000641f248e0a792,0x0001ed1fc53a6622}}
+};
+
+// ****************** modm-donna-64bit.h *********************** //
+
+const bignum256modm modm_m = {
+    0x12631a5cf5d3ed, 0xf9dea2f79cd658,
+    0x000000000014de, 0x00000000000000,
+    0x00000010000000
+};
+
+const bignum256modm modm_mu = {
+    0x9ce5a30a2c131b, 0x215d086329a7ed,
+    0xffffffffeb2106, 0xffffffffffffff,
+    0x00000fffffffff
+};
+
+// *************** ed25519-donna-basepoint-table.h *************** //
+
+/* multiples of the base point in packed {ysubx, xaddy, t2d} form */
+ALIGN(16) const byte ge25519_niels_base_multiples[256][96] = {
+    {0x3e,0x91,0x40,0xd7,0x05,0x39,0x10,0x9d,0xb3,0xbe,0x40,0xd1,0x05,0x9f,0x39,0xfd,0x09,0x8a,0x8f,0x68,0x34,0x84,0xc1,0xa5,0x67,0x12,0xf8,0x98,0x92,0x2f,0xfd,0x44,0x85,0x3b,0x8c,0xf5,0xc6,0x93,0xbc,0x2f,0x19,0x0e,0x8c,0xfb,0xc6,0x2d,0x93,0xcf,0xc2,0x42,0x3d,0x64,0x98,0x48,0x0b,0x27,0x65,0xba,0xd4,0x33,0x3a,0x9d,0xcf,0x07,0x59,0xbb,0x6f,0x4b,0x67,0x15,0xbd,0xdb,0xea,0xa5,0xa2,0xee,0x00,0x3f,0xe1,0x41,0xfa,0xc6,0x57,0xc9,0x1c,0x9d,0xd4,0xcd,0xca,0xec,0x16,0xaf,0x1f,0xbe,0x0e,0x4f},
+    {0xa8,0xd5,0xb4,0x42,0x60,0xa5,0x99,0x8a,0xf6,0xac,0x60,0x4e,0x0c,0x81,0x2b,0x8f,0xaa,0x37,0x6e,0xb1,0x6b,0x23,0x9e,0xe0,0x55,0x25,0xc9,0x69,0xa6,0x95,0xb5,0x6b,0xd7,0x71,0x3c,0x93,0xfc,0xe7,0x24,0x92,0xb5,0xf5,0x0f,0x7a,0x96,0x9d,0x46,0x9f,0x02,0x07,0xd6,0xe1,0x65,0x9a,0xa6,0x5a,0x2e,0x2e,0x7d,0xa8,0x3f,0x06,0x0c,0x59,0x02,0x68,0xd3,0xda,0xaa,0x7e,0x34,0x6e,0x05,0x48,0xee,0x83,0x93,0x59,0xf3,0xba,0x26,0x68,0x07,0xe6,0x10,0xbe,0xca,0x3b,0xb8,0xd1,0x5e,0x16,0x0a,0x4f,0x31,0x49},
+    {0x65,0xd2,0xfc,0xa4,0xe8,0x1f,0x61,0x56,0x7d,0xba,0xc1,0xe5,0xfd,0x53,0xd3,0x3b,0xbd,0xd6,0x4b,0x21,0x1a,0xf3,0x31,0x81,0x62,0xda,0x5b,0x55,0x87,0x15,0xb9,0x2a,0x30,0x97,0xee,0x4c,0xa8,0xb0,0x25,0xaf,0x8a,0x4b,0x86,0xe8,0x30,0x84,0x5a,0x02,0x32,0x67,0x01,0x9f,0x02,0x50,0x1b,0xc1,0xf4,0xf8,0x80,0x9a,0x1b,0x4e,0x16,0x7a,0x34,0x48,0x67,0xf1,0xf4,0x11,0xf2,0x9b,0x95,0xf8,0x2d,0xf6,0x17,0x6b,0x4e,0xb8,0x4e,0x2a,0x72,0x5b,0x07,0x6f,0xde,0xd7,0x21,0x2a,0xbb,0x63,0xb9,0x04,0x9a,0x54},
+    {0xbf,0x18,0x68,0x05,0x0a,0x05,0xfe,0x95,0xa9,0xfa,0x60,0x56,0x71,0x89,0x7e,0x32,0x73,0x50,0xa0,0x06,0xcd,0xe3,0xe8,0xc3,0x9a,0xa4,0x45,0x74,0x4c,0x3f,0x93,0x27,0x9f,0x09,0xfc,0x8e,0xb9,0x51,0x73,0x28,0x38,0x25,0xfd,0x7d,0xf4,0xc6,0x65,0x67,0x65,0x92,0x0a,0xfb,0x3d,0x8d,0x34,0xca,0x27,0x87,0xe5,0x21,0x03,0x91,0x0e,0x68,0xb0,0x26,0x14,0xe5,0xec,0x45,0x1e,0xbf,0x94,0x0f,0xba,0x6d,0x3d,0xc6,0x2b,0xe3,0xc0,0x52,0xf8,0x8c,0xd5,0x74,0x29,0xe4,0x18,0x4c,0xe6,0xb0,0xb1,0x79,0xf0,0x44},
+    {0xba,0xd6,0x47,0xa4,0xc3,0x82,0x91,0x7f,0xb7,0x29,0x27,0x4b,0xd1,0x14,0x00,0xd5,0x87,0xa0,0x64,0xb8,0x1c,0xf1,0x3c,0xe3,0xf3,0x55,0x1b,0xeb,0x73,0x7e,0x4a,0x15,0x33,0xbb,0xa5,0x08,0x44,0xbc,0x12,0xa2,0x02,0xed,0x5e,0xc7,0xc3,0x48,0x50,0x8d,0x44,0xec,0xbf,0x5a,0x0c,0xeb,0x1b,0xdd,0xeb,0x06,0xe2,0x46,0xf1,0xcc,0x45,0x29,0xb3,0x03,0xd0,0xe7,0x79,0xa1,0x32,0xc8,0x7e,0x4d,0x12,0x00,0x0a,0x9d,0x72,0x5f,0xf3,0x8f,0x6d,0x0e,0xa1,0xd4,0xc1,0x62,0x98,0x7a,0xb2,0x38,0x59,0xac,0xb8,0x68},
+    {0xa4,0x8c,0x7d,0x7b,0xb6,0x06,0x98,0x49,0x39,0x27,0xd2,0x27,0x84,0xe2,0x5b,0x57,0xb9,0x53,0x45,0x20,0xe7,0x5c,0x08,0xbb,0x84,0x78,0x41,0xae,0x41,0x4c,0xb6,0x38,0x31,0x71,0x15,0x77,0xeb,0xee,0x0c,0x3a,0x88,0xaf,0xc8,0x00,0x89,0x15,0x27,0x9b,0x36,0xa7,0x59,0xda,0x68,0xb6,0x65,0x80,0xbd,0x38,0xcc,0xa2,0xb6,0x7b,0xe5,0x51,0xa4,0xe3,0x9d,0x68,0x91,0xad,0x9d,0x8f,0x37,0x91,0xfb,0xf8,0x28,0x24,0x5f,0x17,0x88,0xb9,0xcf,0x9f,0x32,0xb5,0x0a,0x05,0x9f,0xc0,0x54,0x13,0xa2,0xdf,0x65,0x78},
+    {0xb1,0x21,0x32,0xaa,0x9a,0x2c,0x6f,0xba,0xa7,0x23,0xba,0x3b,0x53,0x21,0xa0,0x6c,0x3a,0x2c,0x19,0x92,0x4f,0x76,0xea,0x9d,0xe0,0x17,0x53,0x2e,0x5d,0xdd,0x6e,0x1d,0xbf,0xa3,0x4e,0x94,0xd0,0x5c,0x1a,0x6b,0xd2,0xc0,0x9d,0xb3,0x3a,0x35,0x70,0x74,0x49,0x2e,0x54,0x28,0x82,0x52,0xb2,0x71,0x7e,0x92,0x3c,0x28,0x69,0xea,0x1b,0x46,0x36,0xda,0x0f,0xab,0xac,0x8a,0x7a,0x21,0xc8,0x49,0x35,0x3d,0x54,0xc6,0x28,0xa5,0x68,0x75,0xab,0x13,0x8b,0x5b,0xd0,0x37,0x37,0xbc,0x2c,0x3a,0x62,0xef,0x3c,0x23},
+    {0xd9,0x34,0x92,0xf3,0xed,0x5d,0xa7,0xe2,0xf9,0x58,0xb5,0xe1,0x80,0x76,0x3d,0x96,0xfb,0x23,0x3c,0x6e,0xac,0x41,0x27,0x2c,0xc3,0x01,0x0e,0x32,0xa1,0x24,0x90,0x3a,0x8f,0x3e,0xdd,0x04,0x66,0x59,0xb7,0x59,0x2c,0x70,0x88,0xe2,0x77,0x03,0xb3,0x6c,0x23,0xc3,0xd9,0x5e,0x66,0x9c,0x33,0xb1,0x2f,0xe5,0xbc,0x61,0x60,0xe7,0x15,0x09,0x7e,0xa3,0x34,0xa8,0x35,0xe8,0x7d,0xdf,0xea,0x57,0x98,0x68,0xda,0x9c,0xe1,0x8b,0x26,0xb3,0x67,0x71,0x36,0x85,0x11,0x2c,0xc2,0xd5,0xef,0xdb,0xd9,0xb3,0x9e,0x58},
+    {0x5e,0x51,0xaa,0x49,0x54,0x63,0x5b,0xed,0x3a,0x82,0xc6,0x0b,0x9f,0xc4,0x65,0xa8,0xc4,0xd1,0x42,0x5b,0xe9,0x1f,0x0c,0x85,0xb9,0x15,0xd3,0x03,0x6f,0x6d,0xd7,0x30,0x1d,0x9c,0x2f,0x63,0x0e,0xdd,0xcc,0x2e,0x15,0x31,0x89,0x76,0x96,0xb6,0xd0,0x51,0x58,0x7a,0x63,0xa8,0x6b,0xb7,0xdf,0x52,0x39,0xef,0x0e,0xa0,0x49,0x7d,0xd3,0x6d,0xc7,0xe4,0x06,0x21,0x17,0x44,0x44,0x6c,0x69,0x7f,0x8d,0x92,0x80,0xd6,0x53,0xfb,0x26,0x3f,0x4d,0x69,0xa4,0x9e,0x73,0xb4,0xb0,0x4b,0x86,0x2e,0x11,0x97,0xc6,0x10},
+    {0xde,0x5f,0xbe,0x7d,0x27,0xc4,0x93,0x64,0xa2,0x7e,0xad,0x19,0xad,0x4f,0x5d,0x26,0x90,0x45,0x30,0x46,0xc8,0xdf,0x00,0x0e,0x09,0xfe,0x66,0xed,0xab,0x1c,0xe6,0x25,0x05,0xc8,0x58,0x83,0xa0,0x2a,0xa6,0x0c,0x47,0x42,0x20,0x7a,0xe3,0x4a,0x3d,0x6a,0xdc,0xed,0x11,0x3b,0xa6,0xd3,0x64,0x74,0xef,0x06,0x08,0x55,0xaf,0x9b,0xbf,0x03,0x04,0x66,0x58,0xcc,0x28,0xe1,0x13,0x3f,0x7e,0x74,0x59,0xb4,0xec,0x73,0x58,0x6f,0xf5,0x68,0x12,0xcc,0xed,0x3d,0xb6,0xa0,0x2c,0xe2,0x86,0x45,0x63,0x78,0x6d,0x56},
+    {0x34,0x08,0xc1,0x9c,0x9f,0xa4,0x37,0x16,0x51,0xc4,0x9b,0xa8,0xd5,0x56,0x8e,0xbc,0xdb,0xd2,0x7f,0x7f,0x0f,0xec,0xb5,0x1c,0xd9,0x35,0xcc,0x5e,0xca,0x5b,0x97,0x33,0xd0,0x2f,0x5a,0xc6,0x85,0x42,0x05,0xa1,0xc3,0x67,0x16,0xf3,0x2a,0x11,0x64,0x6c,0x58,0xee,0x1a,0x73,0x40,0xe2,0x0a,0x68,0x2a,0xb2,0x93,0x47,0xf3,0xa5,0xfb,0x14,0xd4,0xf7,0x85,0x69,0x16,0x46,0xd7,0x3c,0x57,0x00,0xc8,0xc9,0x84,0x5e,0x3e,0x59,0x1e,0x13,0x61,0x7b,0xb6,0xf2,0xc3,0x2f,0x6c,0x52,0xfc,0x83,0xea,0x9c,0x82,0x14},
+    {0xc2,0x95,0xdd,0x97,0x84,0x7b,0x43,0xff,0xa7,0xb5,0x4e,0xaa,0x30,0x4e,0x74,0x6c,0x8b,0xe8,0x85,0x3c,0x61,0x5d,0x0c,0x9e,0x73,0x81,0x75,0x5f,0x1e,0xc7,0xd9,0x2f,0xb8,0xec,0x71,0x4e,0x2f,0x0b,0xe7,0x21,0xe3,0x77,0xa4,0x40,0xb9,0xdd,0x56,0xe6,0x80,0x4f,0x1d,0xce,0xce,0x56,0x65,0xbf,0x7e,0x7b,0x5d,0x53,0xc4,0x3b,0xfc,0x05,0xdd,0xde,0xaf,0x52,0xae,0xb3,0xb8,0x24,0xcf,0x30,0x3b,0xed,0x8c,0x63,0x95,0x34,0x95,0x81,0xbe,0xa9,0x83,0xbc,0xa4,0x33,0x04,0x1f,0x65,0x5c,0x47,0x67,0x37,0x37},
+    {0xd9,0xad,0xd1,0x40,0xfd,0x99,0xba,0x2f,0x27,0xd0,0xf4,0x96,0x6f,0x16,0x07,0xb3,0xae,0x3b,0xf0,0x15,0x52,0xf0,0x63,0x43,0x99,0xf9,0x18,0x3b,0x6c,0xa5,0xbe,0x1f,0x90,0x65,0x24,0x14,0xcb,0x95,0x40,0x63,0x35,0x55,0xc1,0x16,0x40,0x14,0x12,0xef,0x60,0xbc,0x10,0x89,0x0c,0x14,0x38,0x9e,0x8c,0x7c,0x90,0x30,0x57,0x90,0xf5,0x6b,0x8a,0x5b,0x41,0xe1,0xf1,0x78,0xa7,0x0f,0x7e,0xa7,0xc3,0xba,0xf7,0x9f,0x40,0x06,0x50,0x9a,0xa2,0x9a,0xb8,0xd7,0x52,0x6f,0x56,0x5a,0x63,0x7a,0xf6,0x1c,0x52,0x02},
+    {0x94,0x52,0x9d,0x0a,0x0b,0xee,0x3f,0x51,0x66,0x5a,0xdf,0x0f,0x5c,0xe7,0x98,0x8f,0xce,0x07,0xe1,0xbf,0x88,0x86,0x61,0xd4,0xed,0x2c,0x38,0x71,0x7e,0x0a,0xa0,0x3f,0xe4,0x5e,0x2f,0x77,0x20,0x67,0x14,0xb1,0xce,0x9a,0x07,0x96,0xb1,0x94,0xf8,0xe8,0x4a,0x82,0xac,0x00,0x4d,0x22,0xf8,0x4a,0xc4,0x6c,0xcd,0xf7,0xd9,0x53,0x17,0x00,0x34,0xdb,0x3d,0x96,0x2d,0x23,0x69,0x3c,0x58,0x38,0x97,0xb4,0xda,0x87,0xde,0x1d,0x85,0xf2,0x91,0xa0,0xf9,0xd1,0xd7,0xaa,0xb6,0xed,0x48,0xa0,0x2f,0xfe,0xb5,0x12},
+    {0x4d,0xe3,0xfc,0x96,0xc4,0xfb,0xf0,0x71,0xed,0x5b,0xf3,0xad,0x6b,0x82,0xb9,0x73,0x61,0xc5,0x28,0xff,0x61,0x72,0x04,0xd2,0x6f,0x20,0xb1,0x6f,0xf9,0x76,0x9b,0x74,0x92,0x1e,0x6f,0xad,0x26,0x7c,0x2b,0xdf,0x13,0x89,0x4b,0x50,0x23,0xd3,0x66,0x4b,0xc3,0x8b,0x1c,0x75,0xc0,0x9d,0x40,0x8c,0xb8,0xc7,0x96,0x07,0xc2,0x93,0x7e,0x6f,0x05,0xae,0xa6,0xae,0x04,0xf6,0x5a,0x1f,0x99,0x9c,0xe4,0xbe,0xf1,0x51,0x23,0xc1,0x66,0x6b,0xff,0xee,0xb5,0x08,0xa8,0x61,0x51,0x21,0xe0,0x01,0x0f,0xc1,0xce,0x0f},
+    {0x44,0x1e,0xfe,0x49,0xa6,0x58,0x4d,0x64,0x7e,0x77,0xad,0x31,0xa2,0xae,0xfc,0x21,0xd2,0xd0,0x7f,0x88,0x5a,0x1c,0x44,0x02,0xf3,0x11,0xc5,0x83,0x71,0xaa,0x01,0x49,0x45,0x4e,0x24,0xc4,0x9d,0xd2,0xf2,0x3d,0x0a,0xde,0xd8,0x93,0x74,0x0e,0x02,0x2b,0x4d,0x21,0x0c,0x82,0x7e,0x06,0xc8,0x6c,0x0a,0xb9,0xea,0x6f,0x16,0x79,0x37,0x41,0xf0,0xf8,0x1a,0x8c,0x54,0xb7,0xb1,0x08,0xb4,0x99,0x62,0x24,0x7c,0x7a,0x0f,0xce,0x39,0xd9,0x06,0x1e,0xf9,0xb0,0x60,0xf7,0x13,0x12,0x6d,0x72,0x7b,0x88,0xbb,0x41},
+    {0xbe,0x46,0x43,0x74,0x44,0x7d,0xe8,0x40,0x25,0x2b,0xb5,0x15,0xd4,0xda,0x48,0x1d,0x3e,0x60,0x3b,0xa1,0x18,0x8a,0x3a,0x7c,0xf7,0xbd,0xcd,0x2f,0xc1,0x28,0xb7,0x4e,0xae,0x91,0x66,0x7c,0x59,0x4c,0x23,0x7e,0xc8,0xb4,0x85,0x0a,0x3d,0x9d,0x88,0x64,0xe7,0xfa,0x4a,0x35,0x0c,0xc9,0xe2,0xda,0x1d,0x9e,0x6a,0x0c,0x07,0x1e,0x87,0x0a,0x89,0x89,0xbc,0x4b,0x99,0xb5,0x01,0x33,0x60,0x42,0xdd,0x5b,0x3a,0xae,0x6b,0x73,0x3c,0x9e,0xd5,0x19,0xe2,0xad,0x61,0x0d,0x64,0xd4,0x85,0x26,0x0f,0x30,0xe7,0x3e},
+    {0xb7,0xd6,0x7d,0x9e,0xe4,0x55,0xd2,0xf5,0xac,0x1e,0x0b,0x61,0x5c,0x11,0x16,0x80,0xca,0x87,0xe1,0x92,0x5d,0x97,0x99,0x3c,0xc2,0x25,0x91,0x97,0x62,0x57,0x81,0x13,0x18,0x75,0x1e,0x84,0x47,0x79,0xfa,0x43,0xd7,0x46,0x9c,0x63,0x59,0xfa,0xc6,0xe5,0x74,0x2b,0x05,0xe3,0x1d,0x5e,0x06,0xa1,0x30,0x90,0xb8,0xcf,0xa2,0xc6,0x47,0x7d,0xe0,0xd6,0xf0,0x8e,0x14,0xd0,0xda,0x3f,0x3c,0x6f,0x54,0x91,0x9a,0x74,0x3e,0x9d,0x57,0x81,0xbb,0x26,0x10,0x62,0xec,0x71,0x80,0xec,0xc9,0x34,0x8d,0xf5,0x8c,0x14},
+    {0x27,0xf0,0x34,0x79,0xf6,0x92,0xa4,0x46,0xa9,0x0a,0x84,0xf6,0xbe,0x84,0x99,0x46,0x54,0x18,0x61,0x89,0x2a,0xbc,0xa1,0x5c,0xd4,0xbb,0x5d,0xbd,0x1e,0xfa,0xf2,0x3f,0x6d,0x75,0xe4,0x9a,0x7d,0x2f,0x57,0xe2,0x7f,0x48,0xf3,0x88,0xbb,0x45,0xc3,0x56,0x8d,0xa8,0x60,0x69,0x6d,0x0b,0xd1,0x9f,0xb9,0xa1,0xae,0x4e,0xad,0xeb,0x8f,0x27,0x66,0x39,0x93,0x8c,0x1f,0x68,0xaa,0xb1,0x98,0x0c,0x29,0x20,0x9c,0x94,0x21,0x8c,0x52,0x3c,0x9d,0x21,0x91,0x52,0x11,0x39,0x7b,0x67,0x9c,0xfe,0x02,0xdd,0x04,0x41},
+    {0x2a,0x42,0x24,0x11,0x5e,0xbf,0xb2,0x72,0xb5,0x3a,0xa3,0x98,0x33,0x0c,0xfa,0xa1,0x66,0xb6,0x52,0xfa,0x01,0x61,0xcb,0x94,0xd5,0x53,0xaf,0xaf,0x00,0x3b,0x86,0x2c,0xb8,0x6a,0x09,0xdb,0x06,0x4e,0x21,0x81,0x35,0x4f,0xe4,0x0c,0xc9,0xb6,0xa8,0x21,0xf5,0x2a,0x9e,0x40,0x2a,0xc1,0x24,0x65,0x81,0xa4,0xfc,0x8e,0xa4,0xb5,0x65,0x01,0x76,0x6a,0x84,0xa0,0x74,0xa4,0x90,0xf1,0xc0,0x7c,0x2f,0xcd,0x84,0xf9,0xef,0x12,0x8f,0x2b,0xaa,0x58,0x06,0x29,0x5e,0x69,0xb8,0xc8,0xfe,0xbf,0xd9,0x67,0x1b,0x59},
+    {0xfa,0x9b,0xb4,0x80,0x1c,0x0d,0x2f,0x31,0x8a,0xec,0xf3,0xab,0x5e,0x51,0x79,0x59,0x88,0x1c,0xf0,0x9e,0xc0,0x33,0x70,0x72,0xcb,0x7b,0x8f,0xca,0xc7,0x2e,0xe0,0x3d,0x5d,0xb5,0x18,0x9f,0x71,0xb3,0xb9,0x99,0x1e,0x64,0x8c,0xa1,0xfa,0xe5,0x65,0xe4,0xed,0x05,0x9f,0xc2,0x36,0x11,0x08,0x61,0x8b,0x12,0x30,0x70,0x86,0x4f,0x9b,0x48,0xef,0x92,0xeb,0x3a,0x2d,0x10,0x32,0xd2,0x61,0xa8,0x16,0x61,0xb4,0x53,0x62,0xe1,0x24,0xaa,0x0b,0x19,0xe7,0xab,0x7e,0x3d,0xbf,0xbe,0x6c,0x49,0xba,0xfb,0xf5,0x49},
+    {0xd4,0xcf,0x5b,0x8a,0x10,0x9a,0x94,0x30,0xeb,0x73,0x64,0xbc,0x70,0xdd,0x40,0xdc,0x1c,0x0d,0x7c,0x30,0xc1,0x94,0xc2,0x92,0x74,0x6e,0xfa,0xcb,0x6d,0xa8,0x04,0x56,0x2e,0x57,0x9c,0x1e,0x8c,0x62,0x5d,0x15,0x41,0x47,0x88,0xc5,0xac,0x86,0x4d,0x8a,0xeb,0x63,0x57,0x51,0xf6,0x52,0xa3,0x91,0x5b,0x51,0x67,0x88,0xc2,0xa6,0xa1,0x06,0xb6,0x64,0x17,0x7c,0xd4,0xd1,0x88,0x72,0x51,0x8b,0x41,0xe0,0x40,0x11,0x54,0x72,0xd1,0xf6,0xac,0x18,0x60,0x1a,0x03,0x9f,0xc6,0x42,0x27,0xfe,0x89,0x9e,0x98,0x20},
+    {0x7f,0xcc,0x2d,0x3a,0xfd,0x77,0x97,0x49,0x92,0xd8,0x4f,0xa5,0x2c,0x7c,0x85,0x32,0xa0,0xe3,0x07,0xd2,0x64,0xd8,0x79,0xa2,0x29,0x7e,0xa6,0x0c,0x1d,0xed,0x03,0x04,0x2e,0xec,0xea,0x85,0x8b,0x27,0x74,0x16,0xdf,0x2b,0xcb,0x7a,0x07,0xdc,0x21,0x56,0x5a,0xf4,0xcb,0x61,0x16,0x4c,0x0a,0x64,0xd3,0x95,0x05,0xf7,0x50,0x99,0x0b,0x73,0x52,0xc5,0x4e,0x87,0x35,0x2d,0x4b,0xc9,0x8d,0x6f,0x24,0x98,0xcf,0xc8,0xe6,0xc5,0xce,0x35,0xc0,0x16,0xfa,0x46,0xcb,0xf7,0xcc,0x3d,0x30,0x08,0x43,0x45,0xd7,0x5b},
+    {0xc2,0x4c,0xb2,0x28,0x95,0xd1,0x9a,0x7f,0x81,0xc1,0x35,0x63,0x65,0x54,0x6b,0x7f,0x36,0x72,0xc0,0x4f,0x6e,0xb6,0xb8,0x66,0x83,0xad,0x80,0x73,0x00,0x78,0x3a,0x13,0x2a,0x79,0xe7,0x15,0x21,0x93,0xc4,0x85,0xc9,0xdd,0xcd,0xbd,0xa2,0x89,0x4c,0xc6,0x62,0xd7,0xa3,0xad,0xa8,0x3d,0x1e,0x9d,0x2c,0xf8,0x67,0x30,0x12,0xdb,0xb7,0x5b,0xbe,0x62,0xca,0xc6,0x67,0xf4,0x61,0x09,0xee,0x52,0x19,0x21,0xd6,0x21,0xec,0x04,0x70,0x47,0xd5,0x9b,0x77,0x60,0x23,0x18,0xd2,0xe0,0xf0,0x58,0x6d,0xca,0x0d,0x74},
+    {0x4e,0xce,0xcf,0x52,0x07,0xee,0x48,0xdf,0xb7,0x08,0xec,0x06,0xf3,0xfa,0xff,0xc3,0xc4,0x59,0x54,0xb9,0x2a,0x0b,0x71,0x05,0x8d,0xa3,0x3e,0x96,0xfa,0x25,0x1d,0x16,0x3c,0x43,0x78,0x04,0x57,0x8c,0x1a,0x23,0x9d,0x43,0x81,0xc2,0x0e,0x27,0xb5,0xb7,0x9f,0x07,0xd9,0xe3,0xea,0x99,0xaa,0xdb,0xd9,0x03,0x2b,0x6c,0x25,0xf5,0x03,0x2c,0x7d,0xa4,0x53,0x7b,0x75,0x18,0x0f,0x79,0x79,0x58,0x0c,0xcf,0x30,0x01,0x7b,0x30,0xf9,0xf7,0x7e,0x25,0x77,0x3d,0x90,0x31,0xaf,0xbb,0x96,0xbd,0xbd,0x68,0x94,0x69},
+    {0xcf,0xfe,0xda,0xf4,0x46,0x2f,0x1f,0xbd,0xf7,0xd6,0x7f,0xa4,0x14,0x01,0xef,0x7c,0x7f,0xb3,0x47,0x4a,0xda,0xfd,0x1f,0xd3,0x85,0x57,0x90,0x73,0xa4,0x19,0x52,0x52,0x48,0x19,0xa9,0x6a,0xe6,0x3d,0xdd,0xd8,0xcc,0xd2,0xc0,0x2f,0xc2,0x64,0x50,0x48,0x2f,0xea,0xfd,0x34,0x66,0x24,0x48,0x9b,0x3a,0x2e,0x4a,0x6c,0x4e,0x1c,0x3e,0x29,0xe1,0x12,0x51,0x92,0x4b,0x13,0x6e,0x37,0xa0,0x5d,0xa1,0xdc,0xb5,0x78,0x37,0x70,0x11,0x31,0x1c,0x46,0xaf,0x89,0x45,0xb0,0x23,0x28,0x03,0x7f,0x44,0x5c,0x60,0x5b},
+    {0x89,0x7c,0xc4,0x20,0x59,0x80,0x65,0xb9,0xcc,0x8f,0x3b,0x92,0x0c,0x10,0xf0,0xe7,0x77,0xef,0xe2,0x02,0x65,0x25,0x01,0x00,0xee,0xb3,0xae,0xa8,0xce,0x6d,0xa7,0x24,0x4c,0xf0,0xe7,0xf0,0xc6,0xfe,0xe9,0x3b,0x62,0x49,0xe3,0x75,0x9e,0x57,0x6a,0x86,0x1a,0xe6,0x1d,0x1e,0x16,0xef,0x42,0x55,0xd5,0xbd,0x5a,0xcc,0xf4,0xfe,0x12,0x2f,0x40,0xc7,0xc0,0xdf,0xb2,0x22,0x45,0x0a,0x07,0xa4,0xc9,0x40,0x7f,0x6e,0xd0,0x10,0x68,0xf6,0xcf,0x78,0x41,0x14,0xcf,0xc6,0x90,0x37,0xa4,0x18,0x25,0x7b,0x60,0x5e},
+    {0x18,0x18,0xdf,0x6c,0x8f,0x1d,0xb3,0x58,0xa2,0x58,0x62,0xc3,0x4f,0xa7,0xcf,0x35,0x6e,0x1d,0xe6,0x66,0x4f,0xff,0xb3,0xe1,0xf7,0xd5,0xcd,0x6c,0xab,0xac,0x67,0x50,0x14,0xcf,0x96,0xa5,0x1c,0x43,0x2c,0xa0,0x00,0xe4,0xd3,0xae,0x40,0x2d,0xc4,0xe3,0xdb,0x26,0x0f,0x2e,0x80,0x26,0x45,0xd2,0x68,0x70,0x45,0x9e,0x13,0x33,0x1f,0x20,0x51,0x9d,0x03,0x08,0x6b,0x7f,0x52,0xfd,0x06,0x00,0x7c,0x01,0x64,0x49,0xb1,0x18,0xa8,0xa4,0x25,0x2e,0xb0,0x0e,0x22,0xd5,0x75,0x03,0x46,0x62,0x88,0xba,0x7c,0x39},
+    {0xb2,0x59,0x59,0xf0,0x93,0x30,0xc1,0x30,0x76,0x79,0xa9,0xe9,0x8d,0xa1,0x3a,0xe2,0x26,0x5e,0x1d,0x72,0x91,0xd4,0x2f,0x22,0x3a,0x6c,0x6e,0x76,0x20,0xd3,0x39,0x23,0xe7,0x79,0x13,0xc8,0xfb,0xc3,0x15,0x78,0xf1,0x2a,0xe1,0xdd,0x20,0x94,0x61,0xa6,0xd5,0xfd,0xa8,0x85,0xf8,0xc0,0xa9,0xff,0x52,0xc2,0xe1,0xc1,0x22,0x40,0x1b,0x77,0xa7,0x2f,0x3a,0x51,0x86,0xd9,0x7d,0xd8,0x08,0xcf,0xd4,0xf9,0x71,0x9b,0xac,0xf5,0xb3,0x83,0xa2,0x1e,0x1b,0xc3,0x6b,0xd0,0x76,0x1a,0x97,0x19,0x92,0x18,0x1a,0x33},
+    {0xc6,0x80,0x4f,0xfb,0x45,0x6f,0x16,0xf5,0xcf,0x75,0xc7,0x61,0xde,0xc7,0x36,0x9c,0x1c,0xd9,0x41,0x90,0x1b,0xe8,0xd4,0xe3,0x21,0xfe,0xbd,0x83,0x6b,0x7c,0x16,0x31,0xaf,0x72,0x75,0x9d,0x3a,0x2f,0x51,0x26,0x9e,0x4a,0x07,0x68,0x88,0xe2,0xcb,0x5b,0xc4,0xf7,0x80,0x11,0xc1,0xc1,0xed,0x84,0x7b,0xa6,0x49,0xf6,0x9f,0x61,0xc9,0x1a,0x68,0x10,0x4b,0x52,0x42,0x38,0x2b,0xf2,0x87,0xe9,0x9c,0xee,0x3b,0x34,0x68,0x50,0xc8,0x50,0x62,0x4a,0x84,0x71,0x9d,0xfc,0x11,0xb1,0x08,0x1f,0x34,0x36,0x24,0x61},
+    {0x8d,0x89,0x4e,0x87,0xdb,0x41,0x9d,0xd9,0x20,0xdc,0x07,0x6c,0xf1,0xa5,0xfe,0x09,0xbc,0x9b,0x0f,0xd0,0x67,0x2c,0x3d,0x79,0x40,0xff,0x5e,0x9e,0x30,0xe2,0xeb,0x46,0x38,0x26,0x2d,0x1a,0xe3,0x49,0x63,0x8b,0x35,0xfd,0xd3,0x9b,0x00,0xb7,0xdf,0x9d,0xa4,0x6b,0xa0,0xa3,0xb8,0xf1,0x8b,0x7f,0x45,0x04,0xd9,0x78,0x31,0xaa,0x22,0x15,0x38,0x49,0x61,0x69,0x53,0x2f,0x38,0x2c,0x10,0x6d,0x2d,0xb7,0x9a,0x40,0xfe,0xda,0x27,0xf2,0x46,0xb6,0x91,0x33,0xc8,0xe8,0x6c,0x30,0x24,0x05,0xf5,0x70,0xfe,0x45},
+    {0x8c,0x0b,0x0c,0x96,0xa6,0x75,0x48,0xda,0x20,0x2f,0x0e,0xef,0x76,0xd0,0x68,0x5b,0xd4,0x8f,0x0b,0x3d,0xcf,0x51,0xfb,0x07,0xd4,0x92,0xe3,0xa0,0x23,0x16,0x8d,0x42,0x91,0x14,0x95,0xc8,0x20,0x49,0xf2,0x62,0xa2,0x0c,0x63,0x3f,0xc8,0x07,0xf0,0x05,0xb8,0xd4,0xc9,0xf5,0xd2,0x45,0xbb,0x6f,0x45,0x22,0x7a,0xb5,0x6d,0x9f,0x61,0x16,0xfd,0x08,0xa3,0x01,0x44,0x4a,0x4f,0x08,0xac,0xca,0xa5,0x76,0xc3,0x19,0x22,0xa8,0x7d,0xbc,0xd1,0x43,0x46,0xde,0xb8,0xde,0xc6,0x38,0xbd,0x60,0x2d,0x59,0x81,0x1d},
+    {0x5f,0xac,0x0d,0xa6,0x56,0x87,0x36,0x61,0x57,0xdc,0xab,0xeb,0x6a,0x2f,0xe0,0x17,0x7d,0x0f,0xce,0x4c,0x2d,0x3f,0x19,0x7f,0xf0,0xdc,0xec,0x89,0x77,0x4a,0x23,0x20,0xe8,0xc5,0x85,0x7b,0x9f,0xb6,0x65,0x87,0xb2,0xba,0x68,0xd1,0x8b,0x67,0xf0,0x6f,0x9b,0x0f,0x33,0x1d,0x7c,0xe7,0x70,0x3a,0x7c,0x8e,0xaf,0xb0,0x51,0x6d,0x5f,0x3a,0x52,0xb2,0x78,0x71,0xb6,0x0d,0xd2,0x76,0x60,0xd1,0x1e,0xd5,0xf9,0x34,0x1c,0x07,0x70,0x11,0xe4,0xb3,0x20,0x4a,0x2a,0xf6,0x66,0xe3,0xff,0x3c,0x35,0x82,0xd6,0x7c},
+    {0xb6,0xfa,0x87,0xd8,0x5b,0xa4,0xe1,0x0b,0x6e,0x3b,0x40,0xba,0x32,0x6a,0x84,0x2a,0x00,0x60,0x6e,0xe9,0x12,0x10,0x92,0xd9,0x43,0x09,0xdc,0x3b,0x86,0xc8,0x38,0x28,0xf3,0xf4,0xac,0x68,0x60,0xcd,0x65,0xa6,0xd3,0xe3,0xd7,0x3c,0x18,0x2d,0xd9,0x42,0xd9,0x25,0x60,0x33,0x9d,0x38,0x59,0x57,0xff,0xd8,0x2c,0x2b,0x3b,0x25,0xf0,0x3e,0x30,0x50,0x46,0x4a,0xcf,0xb0,0x6b,0xd1,0xab,0x77,0xc5,0x15,0x41,0x6b,0x49,0xfa,0x9d,0x41,0xab,0xf4,0x8a,0xae,0xcf,0x82,0x12,0x28,0xa8,0x06,0xa6,0xb8,0xdc,0x21},
+    {0xc8,0x9f,0x9d,0x8c,0x46,0x04,0x60,0x5c,0xcb,0xa3,0x2a,0xd4,0x6e,0x09,0x40,0x25,0x9c,0x2f,0xee,0x12,0x4c,0x4d,0x5b,0x12,0xab,0x1d,0xa3,0x94,0x81,0xd0,0xc3,0x0b,0xba,0x31,0x77,0xbe,0xfa,0x00,0x8d,0x9a,0x89,0x18,0x9e,0x62,0x7e,0x60,0x03,0x82,0x7f,0xd9,0xf3,0x43,0x37,0x02,0xcc,0xb2,0x8b,0x67,0x6f,0x6c,0xbf,0x0d,0x84,0x5d,0x8b,0xe1,0x9f,0x30,0x0d,0x38,0x6e,0x70,0xc7,0x65,0xe1,0xb9,0xa6,0x2d,0xb0,0x6e,0xab,0x20,0xae,0x7d,0x99,0xba,0xbb,0x57,0xdd,0x96,0xc1,0x2a,0x23,0x76,0x42,0x3a},
+    {0xfa,0x84,0x70,0x8a,0x2c,0x43,0x42,0x4b,0x45,0xe5,0xb9,0xdf,0xe3,0x19,0x8a,0x89,0x5d,0xe4,0x58,0x9c,0x21,0x00,0x9f,0xbe,0xd1,0xeb,0x6d,0xa1,0xce,0x77,0xf1,0x1f,0xcb,0x7e,0x44,0xdb,0x72,0xc1,0xf8,0x3b,0xbd,0x2d,0x28,0xc6,0x1f,0xc4,0xcf,0x5f,0xfe,0x15,0xaa,0x75,0xc0,0xff,0xac,0x80,0xf9,0xa9,0xe1,0x24,0xe8,0xc9,0x70,0x07,0xfd,0xb5,0xb5,0x45,0x9a,0xd9,0x61,0xcf,0x24,0x79,0x3a,0x1b,0xe9,0x84,0x09,0x86,0x89,0x3e,0x3e,0x30,0x19,0x09,0x30,0xe7,0x1e,0x0b,0x50,0x41,0xfd,0x64,0xf2,0x39},
+    {0x9c,0xe2,0xe7,0xdb,0x17,0x34,0xad,0xa7,0x9c,0x13,0x9c,0x2b,0x6a,0x37,0x94,0xbd,0xa9,0x7b,0x59,0x93,0x8e,0x1b,0xe9,0xa0,0x40,0x98,0x88,0x68,0x34,0xd7,0x12,0x17,0xe1,0x7b,0x09,0xfe,0xab,0x4a,0x9b,0xd1,0x29,0x19,0xe0,0xdf,0xe1,0xfc,0x6d,0xa4,0xff,0xf1,0xa6,0x2c,0x94,0x08,0xc9,0xc3,0x4e,0xf1,0x35,0x2c,0x27,0x21,0xc6,0x65,0xdd,0x93,0x31,0xce,0xf8,0x89,0x2b,0xe7,0xbb,0xc0,0x25,0xa1,0x56,0x33,0x10,0x4d,0x83,0xfe,0x1c,0x2e,0x3d,0xa9,0x19,0x04,0x72,0xe2,0x9c,0xb1,0x0a,0x80,0xf9,0x22},
+    {0xcb,0xf8,0x9e,0x3e,0x8a,0x36,0x5a,0x60,0x15,0x47,0x50,0xa5,0x22,0xc0,0xe9,0xe3,0x8f,0x24,0x24,0x5f,0xb0,0x48,0x3d,0x55,0xe5,0x26,0x76,0x64,0xcd,0x16,0xf4,0x13,0xac,0xfd,0x6e,0x9a,0xdd,0x9f,0x02,0x42,0x41,0x49,0xa5,0x34,0xbe,0xce,0x12,0xb9,0x7b,0xf3,0xbd,0x87,0xb9,0x64,0x0f,0x64,0xb4,0xca,0x98,0x85,0xd3,0xa4,0x71,0x41,0x8c,0x4c,0xc9,0x99,0xaa,0x58,0x27,0xfa,0x07,0xb8,0x00,0xb0,0x6f,0x6f,0x00,0x23,0x92,0x53,0xda,0xad,0xdd,0x91,0xd2,0xfb,0xab,0xd1,0x4b,0x57,0xfa,0x14,0x82,0x50},
+    {0x4b,0xfe,0xd6,0x3e,0x15,0x69,0x02,0xc2,0xc4,0x77,0x1d,0x51,0x39,0x67,0x5a,0xa6,0x94,0xaf,0x14,0x2c,0x46,0x26,0xde,0xcb,0x4b,0xa7,0xab,0x6f,0xec,0x60,0xf9,0x22,0xd6,0x03,0xd0,0x53,0xbb,0x15,0x1a,0x46,0x65,0xc9,0xf3,0xbc,0x88,0x28,0x10,0xb2,0x5a,0x3a,0x68,0x6c,0x75,0x76,0xc5,0x27,0x47,0xb4,0x6c,0xc8,0xa4,0x58,0x77,0x3a,0x76,0x50,0xae,0x93,0xf6,0x11,0x81,0x54,0xa6,0x54,0xfd,0x1d,0xdf,0x21,0xae,0x1d,0x65,0x5e,0x11,0xf3,0x90,0x8c,0x24,0x12,0x94,0xf4,0xe7,0x8d,0x5f,0xd1,0x9f,0x5d},
+    {0x7f,0x72,0x63,0x6d,0xd3,0x08,0x14,0x03,0x33,0xb5,0xc7,0xd7,0xef,0x9a,0x37,0x6a,0x4b,0xe2,0xae,0xcc,0xc5,0x8f,0xe1,0xa9,0xd3,0xbe,0x8f,0x4f,0x91,0x35,0x2f,0x33,0x1e,0x52,0xd7,0xee,0x2a,0x4d,0x24,0x3f,0x15,0x96,0x2e,0x43,0x28,0x90,0x3a,0x8e,0xd4,0x16,0x9c,0x2e,0x77,0xba,0x64,0xe1,0xd8,0x98,0xeb,0x47,0xfa,0x87,0xc1,0x3b,0x0c,0xc2,0x86,0xea,0x15,0x01,0x47,0x6d,0x25,0xd1,0x46,0x6c,0xcb,0xb7,0x8a,0x99,0x88,0x01,0x66,0x3a,0xb5,0x32,0x78,0xd7,0x03,0xba,0x6f,0x90,0xce,0x81,0x0d,0x45},
+    {0x75,0x52,0x20,0xa6,0xa1,0xb6,0x7b,0x6e,0x83,0x8e,0x3c,0x41,0xd7,0x21,0x4f,0xaa,0xb2,0x5c,0x8f,0xe8,0x55,0xd1,0x56,0x6f,0xe1,0x5b,0x34,0xa6,0x4b,0x5d,0xe2,0x2d,0x3f,0x74,0xae,0x1c,0x96,0xd8,0x74,0xd0,0xed,0x63,0x1c,0xee,0xf5,0x18,0x6d,0xf8,0x29,0xed,0xf4,0xe7,0x5b,0xc5,0xbd,0x97,0x08,0xb1,0x3a,0x66,0x79,0xd2,0xba,0x4c,0xcd,0x1f,0xd7,0xa0,0x24,0x90,0xd1,0x80,0xf8,0x8a,0x28,0xfb,0x0a,0xc2,0x25,0xc5,0x19,0x64,0x3a,0x5f,0x4b,0x97,0xa3,0xb1,0x33,0x72,0x00,0xe2,0xef,0xbc,0x7f,0x7d},
+    {0x01,0x28,0x6b,0x26,0x6a,0x1e,0xef,0xfa,0x16,0x9f,0x73,0xd5,0xc4,0x68,0x6c,0x86,0x2c,0x76,0x03,0x1b,0xbc,0x2f,0x8a,0xf6,0x8d,0x5a,0xb7,0x87,0x5e,0x43,0x75,0x59,0x94,0x90,0xc2,0xf3,0xc5,0x5d,0x7c,0xcd,0xab,0x05,0x91,0x2a,0x9a,0xa2,0x81,0xc7,0x58,0x30,0x1c,0x42,0x36,0x1d,0xc6,0x80,0xd7,0xd4,0xd8,0xdc,0x96,0xd1,0x9c,0x4f,0x68,0x37,0x7b,0x6a,0xd8,0x97,0x92,0x19,0x63,0x7a,0xd1,0x1a,0x24,0x58,0xd0,0xd0,0x17,0x0c,0x1c,0x5c,0xad,0x9c,0x02,0xba,0x07,0x03,0x7a,0x38,0x84,0xd0,0xcd,0x7c},
+    {0x17,0x04,0x26,0x6d,0x2c,0x42,0xa6,0xdc,0xbd,0x40,0x82,0x94,0x50,0x3d,0x15,0xae,0x77,0xc6,0x68,0xfb,0xb4,0xc1,0xc0,0xa9,0x53,0xcf,0xd0,0x61,0xed,0xd0,0x8b,0x42,0x93,0xcc,0x60,0x67,0x18,0x84,0x0c,0x9b,0x99,0x2a,0xb3,0x1a,0x7a,0x00,0xae,0xcd,0x18,0xda,0x0b,0x62,0x86,0xec,0x8d,0xa8,0x44,0xca,0x90,0x81,0x84,0xca,0x93,0x35,0xa7,0x9a,0x84,0x5e,0x9a,0x18,0x13,0x92,0xcd,0xfa,0xd8,0x65,0x35,0xc3,0xd8,0xd4,0xd1,0xbb,0xfd,0x53,0x5b,0x54,0x52,0x8c,0xe6,0x63,0x2d,0xda,0x08,0x83,0x39,0x27},
+    {0x13,0xd4,0x5e,0x43,0x28,0x8d,0xc3,0x42,0xc9,0xcc,0x78,0x32,0x60,0xf3,0x50,0xbd,0xef,0x03,0xda,0x79,0x1a,0xab,0x07,0xbb,0x55,0x33,0x8c,0xbe,0xae,0x97,0x95,0x26,0x53,0x24,0x70,0x0a,0x4c,0x0e,0xa1,0xb9,0xde,0x1b,0x7d,0xd5,0x66,0x58,0xa2,0x0f,0xf7,0xda,0x27,0xcd,0xb5,0xd9,0xb9,0xff,0xfd,0x33,0x2c,0x49,0x45,0x29,0x2c,0x57,0xbe,0x30,0xcd,0xd6,0x45,0xc7,0x7f,0xc7,0xfb,0xae,0xba,0xe3,0xd3,0xe8,0xdf,0xe4,0x0c,0xda,0x5d,0xaa,0x30,0x88,0x2c,0xa2,0x80,0xca,0x5b,0xc0,0x98,0x54,0x98,0x7f},
+    {0x17,0xe1,0x0b,0x9f,0x88,0xce,0x49,0x38,0x88,0xa2,0x54,0x7b,0x1b,0xad,0x05,0x80,0x1c,0x92,0xfc,0x23,0x9f,0xc3,0xa3,0x3d,0x04,0xf3,0x31,0x0a,0x47,0xec,0xc2,0x76,0x63,0x63,0xbf,0x0f,0x52,0x15,0x56,0xd3,0xa6,0xfb,0x4d,0xcf,0x45,0x5a,0x04,0x08,0xc2,0xa0,0x3f,0x87,0xbc,0x4f,0xc2,0xee,0xe7,0x12,0x9b,0xd6,0x3c,0x65,0xf2,0x30,0x85,0x0c,0xc1,0xaa,0x38,0xc9,0x08,0x8a,0xcb,0x6b,0x27,0xdb,0x60,0x9b,0x17,0x46,0x70,0xac,0x6f,0x0e,0x1e,0xc0,0x20,0xa9,0xda,0x73,0x64,0x59,0xf1,0x73,0x12,0x2f},
+    {0x11,0x1e,0xe0,0x8a,0x7c,0xfc,0x39,0x47,0x9f,0xab,0x6a,0x4a,0x90,0x74,0x52,0xfd,0x2e,0x8f,0x72,0x87,0x82,0x8a,0xd9,0x41,0xf2,0x69,0x5b,0xd8,0x2a,0x57,0x9e,0x5d,0xc0,0x0b,0xa7,0x55,0xd7,0x8b,0x48,0x30,0xe7,0x42,0xd4,0xf1,0xa4,0xb5,0xd6,0x06,0x62,0x61,0x59,0xbc,0x9e,0xa6,0xd1,0xea,0x84,0xf7,0xc5,0xed,0x97,0x19,0xac,0x38,0x3b,0xb1,0x51,0xa7,0x17,0xb5,0x66,0x06,0x8c,0x85,0x9b,0x7e,0x86,0x06,0x7d,0x74,0x49,0xde,0x4d,0x45,0x11,0xc0,0xac,0xac,0x9c,0xe6,0xe9,0xbf,0x9c,0xcd,0xdf,0x22},
+    {0xd9,0x0c,0x0d,0xc3,0xe0,0xd2,0xdb,0x8d,0x33,0x43,0xbb,0xac,0x5f,0x66,0x8e,0xad,0x1f,0x96,0x2a,0x32,0x8c,0x25,0x6b,0x8f,0xc7,0xc1,0x48,0x54,0xc0,0x16,0x29,0x6b,0xa1,0xe0,0x3b,0x10,0xb4,0x59,0xec,0x56,0x69,0xf9,0x59,0xd2,0xec,0xba,0xe3,0x2e,0x32,0xcd,0xf5,0x13,0x94,0xb2,0x7c,0x79,0x72,0xe4,0xcd,0x24,0x78,0x87,0xe9,0x0f,0x3b,0x91,0xba,0x0a,0xd1,0x34,0xdb,0x7e,0x0e,0xac,0x6d,0x2e,0x82,0xcd,0xa3,0x4e,0x15,0xf8,0x78,0x65,0xff,0x3d,0x08,0x66,0x17,0x0a,0xf0,0x7f,0x30,0x3f,0x30,0x4c},
+    {0x85,0x8c,0xb2,0x17,0xd6,0x3b,0x0a,0xd3,0xea,0x3b,0x77,0x39,0xb7,0x77,0xd3,0xc5,0xbf,0x5c,0x6a,0x1e,0x8c,0xe7,0xc6,0xc6,0xc4,0xb7,0x2a,0x8b,0xf7,0xb8,0x61,0x0d,0x00,0x45,0xd9,0x0d,0x58,0x03,0xfc,0x29,0x93,0xec,0xbb,0x6f,0xa4,0x7a,0xd2,0xec,0xf8,0xa7,0xe2,0xc2,0x5f,0x15,0x0a,0x13,0xd5,0xa1,0x06,0xb7,0x1a,0x15,0x6b,0x41,0xb0,0x36,0xc1,0xe9,0xef,0xd7,0xa8,0x56,0x20,0x4b,0xe4,0x58,0xcd,0xe5,0x07,0xbd,0xab,0xe0,0x57,0x1b,0xda,0x2f,0xe6,0xaf,0xd2,0xe8,0x77,0x42,0xf7,0x2a,0x1a,0x19},
+    {0x31,0x14,0x3c,0xc5,0x4b,0xf7,0x16,0xce,0xde,0xed,0x72,0x20,0xce,0x25,0x97,0x2b,0xe7,0x3e,0xb2,0xb5,0x6f,0xc3,0xb9,0xb8,0x08,0xc9,0x5c,0x0b,0x45,0x0e,0x2e,0x7e,0xfb,0x0e,0x46,0x4f,0x43,0x2b,0xe6,0x9f,0xd6,0x07,0x36,0xa6,0xd4,0x03,0xd3,0xde,0x24,0xda,0xa0,0xb7,0x0e,0x21,0x52,0xf0,0x93,0x5b,0x54,0x00,0xbe,0x7d,0x7e,0x23,0x30,0xb4,0x01,0x67,0xed,0x75,0x35,0x01,0x10,0xfd,0x0b,0x9f,0xe6,0x94,0x10,0x23,0x22,0x7f,0xe4,0x83,0x15,0x0f,0x32,0x75,0xe3,0x55,0x11,0xb1,0x99,0xa6,0xaf,0x71},
+    {0x1d,0xb6,0x53,0x39,0x9b,0x6f,0xce,0x65,0xe6,0x41,0xa1,0xaf,0xea,0x39,0x58,0xc6,0xfe,0x59,0xf7,0xa9,0xfd,0x5f,0x43,0x0f,0x8e,0xc2,0xb1,0xc2,0xe9,0x42,0x11,0x02,0xd6,0x50,0x3b,0x47,0x1c,0x3c,0x42,0xea,0x10,0xef,0x38,0x3b,0x1f,0x7a,0xe8,0x51,0x95,0xbe,0xc9,0xb2,0x5f,0xbf,0x84,0x9b,0x1c,0x9a,0xf8,0x78,0xbc,0x1f,0x73,0x00,0x80,0x18,0xf8,0x48,0x18,0xc7,0x30,0xe4,0x19,0xc1,0xce,0x5e,0x22,0x0c,0x96,0xbf,0xe3,0x15,0xba,0x6b,0x83,0xe0,0xda,0xb6,0x08,0x58,0xe1,0x47,0x33,0x6f,0x4d,0x4c},
+    {0xc9,0x1f,0x7d,0xc1,0xcf,0xec,0xf7,0x18,0x14,0x3c,0x40,0x51,0xa6,0xf5,0x75,0x6c,0xdf,0x0c,0xee,0xf7,0x2b,0x71,0xde,0xdb,0x22,0x7a,0xe4,0xa7,0xaa,0xdd,0x3f,0x19,0x70,0x19,0x8f,0x98,0xfc,0xdd,0x0c,0x2f,0x1b,0xf5,0xb9,0xb0,0x27,0x62,0x91,0x6b,0xbe,0x76,0x91,0x77,0xc4,0xb6,0xc7,0x6e,0xa8,0x9f,0x8f,0xa8,0x00,0x95,0xbf,0x38,0x6f,0x87,0xe8,0x37,0x3c,0xc9,0xd2,0x1f,0x2c,0x46,0xd1,0x18,0x5a,0x1e,0xf6,0xa2,0x76,0x12,0x24,0x39,0x82,0xf5,0x80,0x50,0x69,0x49,0x0d,0xbf,0x9e,0xb9,0x6f,0x6a},
+    {0xeb,0x55,0x08,0x56,0xbb,0xc1,0x46,0x6a,0x9d,0xf0,0x93,0xf8,0x38,0xbb,0x16,0x24,0xc1,0xac,0x71,0x8f,0x37,0x11,0x1d,0xd7,0xea,0x96,0x18,0xa3,0x14,0x69,0xf7,0x75,0xc6,0x23,0xe4,0xb6,0xb5,0x22,0xb1,0xee,0x8e,0xff,0x86,0xf2,0x10,0x70,0x9d,0x93,0x8c,0x5d,0xcf,0x1d,0x83,0x2a,0xa9,0x90,0x10,0xeb,0xc5,0x42,0x9f,0xda,0x6f,0x13,0xd1,0xbd,0x05,0xa3,0xb1,0xdf,0x4c,0xf9,0x08,0x2c,0xf8,0x9f,0x9d,0x4b,0x36,0x0f,0x8a,0x58,0xbb,0xc3,0xa5,0xd8,0x87,0x2a,0xba,0xdc,0xe8,0x0b,0x51,0x83,0x21,0x02},
+    {0x14,0x2d,0xad,0x5e,0x38,0x66,0xf7,0x4a,0x30,0x58,0x7c,0xca,0x80,0xd8,0x8e,0xa0,0x3d,0x1e,0x21,0x10,0xe6,0xa6,0x13,0x0d,0x03,0x6c,0x80,0x7b,0xe1,0x1c,0x07,0x6a,0x7f,0x7a,0x30,0x43,0x01,0x71,0x5a,0x9d,0x5f,0xa4,0x7d,0xc4,0x9e,0xde,0x63,0xb0,0xd3,0x7a,0x92,0xbe,0x52,0xfe,0xbb,0x22,0x6c,0x42,0x40,0xfd,0x41,0xc4,0x87,0x13,0xf8,0x8a,0x97,0x87,0xd1,0xc3,0xd3,0xb5,0x13,0x44,0x0e,0x7f,0x3d,0x5a,0x2b,0x72,0xa0,0x7c,0x47,0xbb,0x48,0x48,0x7b,0x0d,0x92,0xdc,0x1e,0xaf,0x6a,0xb2,0x71,0x31},
+    {0xa8,0x4c,0x56,0x97,0x90,0x31,0x2f,0xa9,0x19,0xe1,0x75,0x22,0x4c,0xb8,0x7b,0xff,0x50,0x51,0x87,0xa4,0x37,0xfe,0x55,0x4f,0x5a,0x83,0xf0,0x3c,0x87,0xd4,0x1f,0x22,0xd1,0x47,0x8a,0xb2,0xd8,0xb7,0x0d,0xa6,0xf1,0xa4,0x70,0x17,0xd6,0x14,0xbf,0xa6,0x58,0xbd,0xdd,0x53,0x93,0xf8,0xa1,0xd4,0xe9,0x43,0x42,0x34,0x63,0x4a,0x51,0x6c,0x41,0x63,0x15,0x3a,0x4f,0x20,0x22,0x23,0x2d,0x03,0x0a,0xba,0xe9,0xe0,0x73,0xfb,0x0e,0x03,0x0f,0x41,0x4c,0xdd,0xe0,0xfc,0xaa,0x4a,0x92,0xfb,0x96,0xa5,0xda,0x48},
+    {0xc7,0x9c,0xa5,0x5c,0x66,0x8e,0xca,0x6e,0xa0,0xac,0x38,0x2e,0x4b,0x25,0x47,0xa8,0xce,0x17,0x1e,0xd2,0x08,0xc7,0xaf,0x31,0xf7,0x4a,0xd8,0xca,0xfc,0xd6,0x6d,0x67,0x93,0x97,0x4c,0xc8,0x5d,0x1d,0xf6,0x14,0x06,0x82,0x41,0xef,0xe3,0xf9,0x41,0x99,0xac,0x77,0x62,0x34,0x8f,0xb8,0xf5,0xcd,0xa9,0x79,0x8a,0x0e,0xfa,0x37,0xc8,0x58,0x58,0x90,0xfc,0x96,0x85,0x68,0xf9,0x0c,0x1b,0xa0,0x56,0x7b,0xf3,0xbb,0xdc,0x1d,0x6a,0xd6,0x35,0x49,0x7d,0xe7,0xc2,0xdc,0x0a,0x7f,0xa5,0xc6,0xf2,0x73,0x4f,0x1c},
+    {0xbb,0xa0,0x5f,0x30,0xbd,0x4f,0x7a,0x0e,0xad,0x63,0xc6,0x54,0xe0,0x4c,0x9d,0x82,0x48,0x38,0xe3,0x2f,0x83,0xc3,0x21,0xf4,0x42,0x4c,0xf6,0x1b,0x0d,0xc8,0x5a,0x79,0x84,0x34,0x7c,0xfc,0x6e,0x70,0x6e,0xb3,0x61,0xcf,0xc1,0xc3,0xb4,0xc9,0xdf,0x73,0xe5,0xc7,0x1c,0x78,0xc9,0x79,0x1d,0xeb,0x5c,0x67,0xaf,0x7d,0xdb,0x9a,0x45,0x70,0xb3,0x2b,0xb4,0x91,0x49,0xdb,0x91,0x1b,0xca,0xdc,0x02,0x4b,0x23,0x96,0x26,0x57,0xdc,0x78,0x8c,0x1f,0xe5,0x9e,0xdf,0x9f,0xd3,0x1f,0xe2,0x8c,0x84,0x62,0xe1,0x5f},
+    {0x1a,0x96,0x94,0xe1,0x4f,0x21,0x59,0x4e,0x4f,0xcd,0x71,0x0d,0xc7,0x7d,0xbe,0x49,0x2d,0xf2,0x50,0x3b,0xd2,0xcf,0x00,0x93,0x32,0x72,0x91,0xfc,0x46,0xd4,0x89,0x47,0x08,0xb2,0x7c,0x5d,0x2d,0x85,0x79,0x28,0xe7,0xf2,0x7d,0x68,0x70,0xdd,0xde,0xb8,0x91,0x78,0x68,0x21,0xab,0xff,0x0b,0xdc,0x35,0xaa,0x7d,0x67,0x43,0xc0,0x44,0x2b,0x8e,0xb7,0x4e,0x07,0xab,0x87,0x1c,0x1a,0x67,0xf4,0xda,0x99,0x8e,0xd1,0xc6,0xfa,0x67,0x90,0x4f,0x48,0xcd,0xbb,0xac,0x3e,0xe4,0xa4,0xb9,0x2b,0xef,0x2e,0xc5,0x60},
+    {0xf1,0x8b,0xfd,0x3b,0xbc,0x89,0x5d,0x0b,0x1a,0x55,0xf3,0xc9,0x37,0x92,0x6b,0xb0,0xf5,0x28,0x30,0xd5,0xb0,0x16,0x4c,0x0e,0xab,0xca,0xcf,0x2c,0x31,0x9c,0xbc,0x10,0x11,0x6d,0xae,0x7c,0xc2,0xc5,0x2b,0x70,0xab,0x8c,0xa4,0x54,0x9b,0x69,0xc7,0x44,0xb2,0x2e,0x49,0xba,0x56,0x40,0xbc,0xef,0x6d,0x67,0xb6,0xd9,0x48,0x72,0xd7,0x70,0x5b,0xa0,0xc2,0x3e,0x4b,0xe8,0x8a,0xaa,0xe0,0x81,0x17,0xed,0xf4,0x9e,0x69,0x98,0xd1,0x85,0x8e,0x70,0xe4,0x13,0x45,0x79,0x13,0xf4,0x76,0xa9,0xd3,0x5b,0x75,0x63},
+    {0x53,0x08,0xd1,0x2a,0x3e,0xa0,0x5f,0xb5,0x69,0x35,0xe6,0x9e,0x90,0x75,0x6f,0x35,0x90,0xb8,0x69,0xbe,0xfd,0xf1,0xf9,0x9f,0x84,0x6f,0xc1,0x8b,0xc4,0xc1,0x8c,0x0d,0xb7,0xac,0xf1,0x97,0x18,0x10,0xc7,0x3d,0xd8,0xbb,0x65,0xc1,0x5e,0x7d,0xda,0x5d,0x0f,0x02,0xa1,0x0f,0x9c,0x5b,0x8e,0x50,0x56,0x2a,0xc5,0x37,0x17,0x75,0x63,0x27,0xa9,0x19,0xb4,0x6e,0xd3,0x02,0x94,0x02,0xa5,0x60,0xb4,0x77,0x7e,0x4e,0xb4,0xf0,0x56,0x49,0x3c,0xd4,0x30,0x62,0xa8,0xcf,0xe7,0x66,0xd1,0x7a,0x8a,0xdd,0xc2,0x70},
+    {0x0e,0xec,0x6f,0x9f,0x50,0x94,0x61,0x65,0x8d,0x51,0xc6,0x46,0xa9,0x7e,0x2e,0xee,0x5c,0x9b,0xe0,0x67,0xf3,0xc1,0x33,0x97,0x95,0x84,0x94,0x63,0x63,0xac,0x0f,0x2e,0x13,0x7e,0xed,0xb8,0x7d,0x96,0xd4,0x91,0x7a,0x81,0x76,0xd7,0x0a,0x2f,0x25,0x74,0x64,0x25,0x85,0x0d,0xe0,0x82,0x09,0xe4,0xe5,0x3c,0xa5,0x16,0x38,0x61,0xb8,0x32,0x64,0xcd,0x48,0xe4,0xbe,0xf7,0xe7,0x79,0xd0,0x86,0x78,0x08,0x67,0x3a,0xc8,0x6a,0x2e,0xdb,0xe4,0xa0,0xd9,0xd4,0x9f,0xf8,0x41,0x4f,0x5a,0x73,0x5c,0x21,0x79,0x41},
+    {0x2a,0xed,0xdc,0xd7,0xe7,0x94,0x70,0x8c,0x70,0x9c,0xd3,0x47,0xc3,0x8a,0xfb,0x97,0x02,0xd9,0x06,0xa9,0x33,0xe0,0x3b,0xe1,0x76,0x9d,0xd9,0x0c,0xa3,0x44,0x03,0x70,0x34,0xcd,0x6b,0x28,0xb9,0x33,0xae,0xe4,0xdc,0xd6,0x9d,0x55,0xb6,0x7e,0xef,0xb7,0x1f,0x8e,0xd3,0xb3,0x1f,0x14,0x8b,0x27,0x86,0xc2,0x41,0x22,0x66,0x85,0xfa,0x31,0xf4,0x22,0x36,0x2e,0x42,0x6c,0x82,0xaf,0x2d,0x50,0x33,0x98,0x87,0x29,0x20,0xc1,0x23,0x91,0x38,0x2b,0xe1,0xb7,0xc1,0x9b,0x89,0x24,0x95,0xa9,0x12,0x23,0xbb,0x24},
+    {0xc3,0x67,0xde,0x32,0x17,0xed,0xa8,0xb1,0x48,0x49,0x1b,0x46,0x18,0x94,0xb4,0x3c,0xd2,0xbc,0xcf,0x76,0x43,0x43,0xbd,0x8e,0x08,0x80,0x18,0x1e,0x87,0x3e,0xee,0x0f,0x6b,0x5c,0xf8,0xf5,0x2a,0x0c,0xf8,0x41,0x94,0x67,0xfa,0x04,0xc3,0x84,0x72,0x68,0xad,0x1b,0xba,0xa3,0x99,0xdf,0x45,0x89,0x16,0x5d,0xeb,0xff,0xf9,0x2a,0x1d,0x0d,0xdf,0x1e,0x62,0x32,0xa1,0x8a,0xda,0xa9,0x79,0x65,0x22,0x59,0xa1,0x22,0xb8,0x30,0x93,0xc1,0x9a,0xa7,0x7b,0x19,0x04,0x40,0x76,0x1d,0x53,0x18,0x97,0xd7,0xac,0x16},
+    {0x3d,0x1d,0x9b,0x2d,0xaf,0x72,0xdf,0x72,0x5a,0x24,0x32,0xa4,0x36,0x2a,0x46,0x63,0x37,0x96,0xb3,0x16,0x79,0xa0,0xce,0x3e,0x09,0x23,0x30,0xb9,0xf6,0x0e,0x3e,0x12,0xad,0xb6,0x87,0x78,0xc5,0xc6,0x59,0xc9,0xba,0xfe,0x90,0x5f,0xad,0x9e,0xe1,0x94,0x04,0xf5,0x42,0xa3,0x62,0x4e,0xe2,0x16,0x00,0x17,0x16,0x18,0x4b,0xd3,0x4e,0x16,0x9a,0xe6,0x2f,0x19,0x4c,0xd9,0x7e,0x48,0x13,0x15,0x91,0x3a,0xea,0x2c,0xae,0x61,0x27,0xde,0xa4,0xb9,0xd3,0xf6,0x7b,0x87,0xeb,0xf3,0x73,0x10,0xc6,0x0f,0xda,0x78},
+    {0x6a,0xc6,0x2b,0xe5,0x28,0x5d,0xf1,0x5b,0x8e,0x1a,0xf0,0x70,0x18,0xe3,0x47,0x2c,0xdd,0x8b,0xc2,0x06,0xbc,0xaf,0x19,0x24,0x3a,0x17,0x6b,0x25,0xeb,0xde,0x25,0x2d,0x94,0x3a,0x0c,0x68,0xf1,0x80,0x9f,0xa2,0xe6,0xe7,0xe9,0x1a,0x15,0x7e,0xf7,0x71,0x73,0x79,0x01,0x48,0x58,0xf1,0x00,0x11,0xdd,0x8d,0xb3,0x16,0xb3,0xa4,0x4a,0x05,0xb8,0x7c,0x26,0x19,0x8d,0x46,0xc8,0xdf,0xaf,0x4d,0xe5,0x66,0x9c,0x78,0x28,0x0b,0x17,0xec,0x6e,0x66,0x2a,0x1d,0xeb,0x2a,0x60,0xa7,0x7d,0xab,0xa6,0x10,0x46,0x13},
+    {0xfe,0xb0,0xf6,0x8d,0xc7,0x8e,0x13,0x51,0x1b,0xf5,0x75,0xe5,0x89,0xda,0x97,0x53,0xb9,0xf1,0x7a,0x71,0x1d,0x7a,0x20,0x09,0x50,0xd6,0x20,0x2b,0xba,0xfd,0x02,0x21,0x15,0xf5,0xd1,0x77,0xe7,0x65,0x2a,0xcd,0xf1,0x60,0xaa,0x8f,0x87,0x91,0x89,0x54,0xe5,0x06,0xbc,0xda,0xbc,0x3b,0xb7,0xb1,0xfb,0xc9,0x7c,0xa9,0xcb,0x78,0x48,0x65,0xa1,0xe6,0x5c,0x05,0x05,0xe4,0x9e,0x96,0x29,0xad,0x51,0x12,0x68,0xa7,0xbc,0x36,0x15,0xa4,0x7d,0xaa,0x17,0xf5,0x1a,0x3a,0xba,0xb2,0xec,0x29,0xdb,0x25,0xd7,0x0a},
+    {0x57,0x24,0x4e,0x83,0xb1,0x67,0x42,0xdc,0xc5,0x1b,0xce,0x70,0xb5,0x44,0x75,0xb6,0xd7,0x5e,0xd1,0xf7,0x0b,0x7a,0xf0,0x1a,0x50,0x36,0xa0,0x71,0xfb,0xcf,0xef,0x4a,0x85,0x6f,0x05,0x9b,0x0c,0xbc,0xc7,0xfe,0xd7,0xff,0xf5,0xe7,0x68,0x52,0x7d,0x53,0xfa,0xae,0x12,0x43,0x62,0xc6,0xaf,0x77,0xd9,0x9f,0x39,0x02,0x53,0x5f,0x67,0x4f,0x1e,0x17,0x15,0x04,0x36,0x36,0x2d,0xc3,0x3b,0x48,0x98,0x89,0x11,0xef,0x2b,0xcd,0x10,0x51,0x94,0xd0,0xad,0x6e,0x0a,0x87,0x61,0x65,0xa8,0xa2,0x72,0xbb,0xcc,0x0b},
+    {0xc8,0xa9,0xb1,0xea,0x2f,0x96,0x5e,0x18,0xcd,0x7d,0x14,0x65,0x35,0xe6,0xe7,0x86,0xf2,0x6d,0x5b,0xbb,0x31,0xe0,0x92,0xb0,0x3e,0xb7,0xd6,0x59,0xab,0xf0,0x24,0x40,0x96,0x12,0xfe,0x50,0x4c,0x5e,0x6d,0x18,0x7e,0x9f,0xe8,0xfe,0x82,0x7b,0x39,0xe0,0xb0,0x31,0x70,0x50,0xc5,0xf6,0xc7,0x3b,0xc2,0x37,0x8f,0x10,0x69,0xfd,0x78,0x66,0xc2,0x63,0x68,0x63,0x31,0xfa,0x86,0x15,0xf2,0x33,0x2d,0x57,0x48,0x8c,0xf6,0x07,0xfc,0xae,0x9e,0x78,0x9f,0xcc,0x73,0x4f,0x01,0x47,0xad,0x8e,0x10,0xe2,0x42,0x2d},
+    {0x9b,0xd2,0xdf,0x94,0x15,0x13,0xf5,0x97,0x6a,0x4c,0x3f,0x31,0x5d,0x98,0x55,0x61,0x10,0x50,0x45,0x08,0x07,0x3f,0xa1,0xeb,0x22,0xd3,0xd2,0xb8,0x08,0x26,0x6b,0x67,0x93,0x75,0x53,0x0f,0x0d,0x7b,0x71,0x21,0x4c,0x06,0x1e,0x13,0x0b,0x69,0x4e,0x91,0x9f,0xe0,0x2a,0x75,0xae,0x87,0xb6,0x1b,0x6e,0x3c,0x42,0x9b,0xa7,0xf3,0x0b,0x42,0x47,0x2b,0x5b,0x1c,0x65,0xba,0x38,0x81,0x80,0x1b,0x1b,0x31,0xec,0xb6,0x71,0x86,0xb0,0x35,0x31,0xbc,0xb1,0x0c,0xff,0x7b,0xe0,0xf1,0x0c,0x9c,0xfa,0x2f,0x5d,0x74},
+    {0xbd,0xc8,0xc9,0x2b,0x1e,0x5a,0x52,0xbf,0x81,0x9d,0x47,0x26,0x08,0x26,0x5b,0xea,0xdb,0x55,0x01,0xdf,0x0e,0xc7,0x11,0xd5,0xd0,0xf5,0x0c,0x96,0xeb,0x3c,0xe2,0x1a,0x6a,0x4e,0xd3,0x21,0x57,0xdf,0x36,0x60,0xd0,0xb3,0x7b,0x99,0x27,0x88,0xdb,0xb1,0xfa,0x6a,0x75,0xc8,0xc3,0x09,0xc2,0xd3,0x39,0xc8,0x1d,0x4c,0xe5,0x5b,0xe1,0x06,0x4a,0x99,0x32,0x19,0x87,0x5d,0x72,0x5b,0xb0,0xda,0xb1,0xce,0xb5,0x1c,0x35,0x32,0x05,0xca,0xb7,0xda,0x49,0x15,0xc4,0x7d,0xf7,0xc1,0x8e,0x27,0x61,0xd8,0xde,0x58},
+    {0x5c,0xc5,0x66,0xf2,0x93,0x37,0x17,0xd8,0x49,0x4e,0x45,0xcc,0xc5,0x76,0xc9,0xc8,0xa8,0xc3,0x26,0xbc,0xf8,0x82,0xe3,0x5c,0xf9,0xf6,0x85,0x54,0xe8,0x9d,0xf3,0x2f,0xa8,0xc9,0xc2,0xb6,0xa8,0x5b,0xfb,0x2d,0x8c,0x59,0x2c,0xf5,0x8e,0xef,0xee,0x48,0x73,0x15,0x2d,0xf1,0x07,0x91,0x80,0x33,0xd8,0x5b,0x1d,0x53,0x6b,0x69,0xba,0x08,0x7a,0xc5,0xef,0xc3,0xee,0x3e,0xed,0x77,0x11,0x48,0xff,0xd4,0x17,0x55,0xe0,0x04,0xcb,0x71,0xa6,0xf1,0x3f,0x7a,0x3d,0xea,0x54,0xfe,0x7c,0x94,0xb4,0x33,0x06,0x12},
+    {0x42,0x00,0x61,0x91,0x78,0x98,0x94,0x0b,0xe8,0xfa,0xeb,0xec,0x3c,0xb1,0xe7,0x4e,0xc0,0xa4,0xf0,0x94,0x95,0x73,0xbe,0x70,0x85,0x91,0xd5,0xb4,0x99,0x0a,0xd3,0x35,0x0a,0x10,0x12,0x49,0x47,0x31,0xbd,0x82,0x06,0xbe,0x6f,0x7e,0x6d,0x7b,0x23,0xde,0xc6,0x79,0xea,0x11,0x19,0x76,0x1e,0xe1,0xde,0x3b,0x39,0xcb,0xe3,0x3b,0x43,0x07,0xf4,0x97,0xe9,0x5c,0xc0,0x44,0x79,0xff,0xa3,0x51,0x5c,0xb0,0xe4,0x3d,0x5d,0x57,0x7c,0x84,0x76,0x5a,0xfd,0x81,0x33,0x58,0x9f,0xda,0xf6,0x7a,0xde,0x3e,0x87,0x2d},
+    {0x09,0x34,0x37,0x43,0x64,0x31,0x7a,0x15,0xd9,0x81,0xaa,0xf4,0xee,0xb7,0xb8,0xfa,0x06,0x48,0xa6,0xf5,0xe6,0xfe,0x93,0xb0,0xb6,0xa7,0x7f,0x70,0x54,0x36,0x77,0x2e,0x81,0xf9,0x5d,0x4e,0xe1,0x02,0x62,0xaa,0xf5,0xe1,0x15,0x50,0x17,0x59,0x0d,0xa2,0x6c,0x1d,0xe2,0xba,0xd3,0x75,0xa2,0x18,0x53,0x02,0x60,0x01,0x8a,0x61,0x43,0x05,0xc1,0x23,0x4c,0x97,0xf4,0xbd,0xea,0x0d,0x93,0x46,0xce,0x9d,0x25,0x0a,0x6f,0xaa,0x2c,0xba,0x9a,0xa2,0xb8,0x2c,0x20,0x04,0x0d,0x96,0x07,0x2d,0x36,0x43,0x14,0x4b},
+    {0x7a,0x1f,0x6e,0xb6,0xc7,0xb7,0xc4,0xcc,0x7e,0x2f,0x0c,0xf5,0x25,0x7e,0x15,0x44,0x1c,0xaf,0x3e,0x71,0xfc,0x6d,0xf0,0x3e,0xf7,0x63,0xda,0x52,0x67,0x44,0x2f,0x58,0xcb,0x9c,0x52,0x1c,0xe9,0x54,0x7c,0x96,0xfb,0x35,0xc6,0x64,0x92,0x26,0xf6,0x30,0x65,0x19,0x12,0x78,0xf4,0xaf,0x47,0x27,0x5c,0x6f,0xf6,0xea,0x18,0x84,0x03,0x17,0xe4,0x4c,0x32,0x20,0xd3,0x7b,0x31,0xc6,0xc4,0x8b,0x48,0xa4,0xe8,0x42,0x10,0xa8,0x64,0x13,0x5a,0x4e,0x8b,0xf1,0x1e,0xb2,0xc9,0x8d,0xa2,0xcd,0x4b,0x1c,0x2a,0x0c},
+    {0x47,0x04,0x1f,0x6f,0xd0,0xc7,0x4d,0xd2,0x59,0xc0,0x87,0xdb,0x3e,0x9e,0x26,0xb2,0x8f,0xd2,0xb2,0xfb,0x72,0x02,0x5b,0xd1,0x77,0x48,0xf6,0xc6,0xd1,0x8b,0x55,0x7c,0x45,0x69,0xbd,0x69,0x48,0x81,0xc4,0xed,0x22,0x8d,0x1c,0xbe,0x7d,0x90,0x6d,0x0d,0xab,0xc5,0x5c,0xd5,0x12,0xd2,0x3b,0xc6,0x83,0xdc,0x14,0xa3,0x30,0x9b,0x6a,0x5a,0x3d,0x46,0x96,0xd3,0x24,0x15,0xec,0xd0,0xf0,0x24,0x5a,0xc3,0x8a,0x62,0xbb,0x12,0xa4,0x5f,0xbc,0x1c,0x79,0x3a,0x0c,0xa5,0xc3,0xaf,0xfb,0x0a,0xca,0xa5,0x04,0x04},
+    {0xd6,0x43,0xa7,0x0a,0x07,0x40,0x1f,0x8c,0xe8,0x5e,0x26,0x5b,0xcb,0xd0,0xba,0xcc,0xde,0xd2,0x8f,0x66,0x6b,0x04,0x4b,0x57,0x33,0x96,0xdd,0xca,0xfd,0x5b,0x39,0x46,0xd1,0x6f,0x41,0x2a,0x1b,0x9e,0xbc,0x62,0x8b,0x59,0x50,0xe3,0x28,0xf7,0xc6,0xb5,0x67,0x69,0x5d,0x3d,0xd8,0x3f,0x34,0x04,0x98,0xee,0xf8,0xe7,0x16,0x75,0x52,0x39,0x9c,0x9a,0x5d,0x1a,0x2d,0xdb,0x7f,0x11,0x2a,0x5c,0x00,0xd1,0xbc,0x45,0x77,0x9c,0xea,0x6f,0xd5,0x54,0xf1,0xbe,0xd4,0xef,0x16,0xd0,0x22,0xe8,0x29,0x9a,0x57,0x76},
+    {0x17,0x2a,0xc0,0x49,0x7e,0x8e,0xb6,0x45,0x7f,0xa3,0xa9,0xbc,0xa2,0x51,0xcd,0x23,0x1b,0x4c,0x22,0xec,0x11,0x5f,0xd6,0x3e,0xb1,0xbd,0x05,0x9e,0xdc,0x84,0xa3,0x43,0xf2,0x34,0xb4,0x52,0x13,0xb5,0x3c,0x33,0xe1,0x80,0xde,0x93,0x49,0x28,0x32,0xd8,0xce,0x35,0x0d,0x75,0x87,0x28,0x51,0xb5,0xc1,0x77,0x27,0x2a,0xbb,0x14,0xc5,0x02,0x45,0xb6,0xf1,0x8b,0xda,0xd5,0x4b,0x68,0x53,0x4b,0xb5,0xf6,0x7e,0xd3,0x8b,0xfb,0x53,0xd2,0xb0,0xa9,0xd7,0x16,0x39,0x31,0x59,0x80,0x54,0x61,0x09,0x92,0x60,0x11},
+    {0xaa,0xcf,0xda,0x29,0x69,0x16,0x4d,0xb4,0x8f,0x59,0x13,0x84,0x4c,0x9f,0x52,0xda,0x59,0x55,0x3d,0x45,0xca,0x63,0xef,0xe9,0x0b,0x8e,0x69,0xc5,0x5b,0x12,0x1e,0x35,0xcd,0x4d,0x9b,0x36,0x16,0x56,0x38,0x7a,0x63,0x35,0x5c,0x65,0xa7,0x2c,0xc0,0x75,0x21,0x80,0xf1,0xd4,0xf9,0x1b,0xc2,0x7d,0x42,0xe0,0xe6,0x91,0x74,0x7d,0x63,0x2f,0xbe,0x7b,0xf6,0x1a,0x46,0x9b,0xb4,0xd4,0x61,0x89,0xab,0xc8,0x7a,0x03,0x03,0xd6,0xfb,0x99,0xa6,0xf9,0x9f,0xe1,0xde,0x71,0x9a,0x2a,0xce,0xe7,0x06,0x2d,0x18,0x7f},
+    {0xec,0x68,0x01,0xab,0x64,0x8e,0x7c,0x7a,0x43,0xc5,0xed,0x15,0x55,0x4a,0x5a,0xcb,0xda,0x0e,0xcd,0x47,0xd3,0x19,0x55,0x09,0xb0,0x93,0x3e,0x34,0x8c,0xac,0xd4,0x67,0x22,0x75,0x21,0x8e,0x72,0x4b,0x45,0x09,0xd8,0xb8,0x84,0xd4,0xf4,0xe8,0x58,0xaa,0x3c,0x90,0x46,0x7f,0x4d,0x25,0x58,0xd3,0x17,0x52,0x1c,0x24,0x43,0xc0,0xac,0x44,0x77,0x57,0x7a,0x4f,0xbb,0x6b,0x7d,0x1c,0xe1,0x13,0x83,0x91,0xd4,0xfe,0x35,0x8b,0x84,0x46,0x6b,0xc9,0xc6,0xa1,0xdc,0x4a,0xbd,0x71,0xad,0x12,0x83,0x1c,0x6d,0x55},
+    {0x82,0x39,0x8d,0x0c,0xe3,0x40,0xef,0x17,0x34,0xfa,0xa3,0x15,0x3e,0x07,0xf7,0x31,0x6e,0x64,0x73,0x07,0xcb,0xf3,0x21,0x4f,0xff,0x4e,0x82,0x1d,0x6d,0x6c,0x6c,0x74,0x21,0xe8,0x1b,0xb1,0x56,0x67,0xf0,0x81,0xdd,0xf3,0xa3,0x10,0x23,0xf8,0xaf,0x0f,0x5d,0x46,0x99,0x6a,0x55,0xd0,0xb2,0xf8,0x05,0x7f,0x8c,0xcc,0x38,0xbe,0x7a,0x09,0xa4,0x2d,0xa5,0x7e,0x87,0xc9,0x49,0x0c,0x43,0x1d,0xdc,0x9b,0x55,0x69,0x43,0x4c,0xd2,0xeb,0xcc,0xf7,0x09,0x38,0x2c,0x02,0xbd,0x84,0xee,0x4b,0xa3,0x14,0x7e,0x57},
+    {0x0a,0x3b,0xa7,0x61,0xac,0x68,0xe2,0xf0,0xf5,0xa5,0x91,0x37,0x10,0xfa,0xfa,0xf2,0xe9,0x00,0x6d,0x6b,0x82,0x3e,0xe1,0xc1,0x42,0x8f,0xd7,0x6f,0xe9,0x7e,0xfa,0x60,0x2b,0xd7,0x4d,0xbd,0xbe,0xce,0xfe,0x94,0x11,0x22,0x0f,0x06,0xda,0x4f,0x6a,0xf4,0xff,0xd1,0xc8,0xc0,0x77,0x59,0x4a,0x12,0x95,0x92,0x00,0xfb,0xb8,0x04,0x53,0x70,0xc6,0x6e,0x29,0x4d,0x35,0x1d,0x3d,0xb6,0xd8,0x31,0xad,0x5f,0x3e,0x05,0xc3,0xf3,0xec,0x42,0xbd,0xb4,0x8c,0x95,0x0b,0x67,0xfd,0x53,0x63,0xa1,0x0c,0x8e,0x39,0x21},
+    {0xf3,0x33,0x2b,0x38,0x8a,0x05,0xf5,0x89,0xb4,0xc0,0x48,0xad,0x0b,0xba,0xe2,0x5a,0x6e,0xb3,0x3d,0xa5,0x03,0xb5,0x93,0x8f,0xe6,0x32,0xa2,0x95,0x9d,0xed,0xa3,0x5a,0x01,0x56,0xb7,0xb4,0xf9,0xaa,0x98,0x27,0x72,0xad,0x8d,0x5c,0x13,0x72,0xac,0x5e,0x23,0xa0,0xb7,0x61,0x61,0xaa,0xce,0xd2,0x4e,0x7d,0x8f,0xe9,0x84,0xb2,0xbf,0x1b,0x61,0x65,0xd9,0xc7,0xe9,0x77,0x67,0x65,0x36,0x80,0xc7,0x72,0x54,0x12,0x2b,0xcb,0xee,0x6e,0x50,0xd9,0x99,0x32,0x05,0x65,0xcc,0x57,0x89,0x5e,0x4e,0xe1,0x07,0x4a},
+    {0x99,0xf9,0x0d,0x98,0xcb,0x12,0xe4,0x4e,0x71,0xc7,0x6e,0x3c,0x6f,0xd7,0x15,0xa3,0xfd,0x77,0x5c,0x92,0xde,0xed,0xa5,0xbb,0x02,0x34,0x31,0x1d,0x39,0xac,0x0b,0x3f,0x9b,0xa4,0x77,0xc4,0xcd,0x58,0x0b,0x24,0x17,0xf0,0x47,0x64,0xde,0xda,0x38,0xfd,0xad,0x6a,0xc8,0xa7,0x32,0x8d,0x92,0x19,0x81,0xa0,0xaf,0x84,0xed,0x7a,0xaf,0x50,0xe5,0x5b,0xf6,0x15,0x01,0xde,0x4f,0x6e,0xb2,0x09,0x61,0x21,0x21,0x26,0x98,0x29,0xd9,0xd6,0xad,0x0b,0x81,0x05,0x02,0x78,0x06,0xd0,0xeb,0xba,0x16,0xa3,0x21,0x19},
+    {0xfc,0x70,0xb8,0xdf,0x7e,0x2f,0x42,0x89,0xbd,0xb3,0x76,0x4f,0xeb,0x6b,0x29,0x2c,0xf7,0x4d,0xc2,0x36,0xd4,0xf1,0x38,0x07,0xb0,0xae,0x73,0xe2,0x41,0xdf,0x58,0x64,0x8b,0xc1,0xf3,0xd9,0x9a,0xad,0x5a,0xd7,0x9c,0xc1,0xb1,0x60,0xef,0x0e,0x6a,0x56,0xd9,0x0e,0x5c,0x25,0xac,0x0b,0x9a,0x3e,0xf5,0xc7,0x62,0xa0,0xec,0x9d,0x04,0x7b,0x83,0x44,0x44,0x35,0x7a,0xe3,0xcb,0xdc,0x93,0xbe,0xed,0x0f,0x33,0x79,0x88,0x75,0x87,0xdd,0xc5,0x12,0xc3,0x04,0x60,0x78,0x64,0x0e,0x95,0xc2,0xcb,0xdc,0x93,0x60},
+    {0x6d,0x70,0xe0,0x85,0x85,0x9a,0xf3,0x1f,0x33,0x39,0xe7,0xb3,0xd8,0xa5,0xd0,0x36,0x3b,0x45,0x8f,0x71,0xe1,0xf2,0xb9,0x43,0x7c,0xa9,0x27,0x48,0x08,0xea,0xd1,0x57,0x4b,0x03,0x84,0x60,0xbe,0xee,0xde,0x6b,0x54,0xb8,0x0f,0x78,0xb6,0xc2,0x99,0x31,0x95,0x06,0x2d,0xb6,0xab,0x76,0x33,0x97,0x90,0x7d,0x64,0x8b,0xc9,0x80,0x31,0x6e,0x71,0xb0,0x28,0xa1,0xe7,0xb6,0x7a,0xee,0xaa,0x8b,0xa8,0x93,0x6d,0x59,0xc1,0xa4,0x30,0x61,0x21,0xb2,0x82,0xde,0xb4,0xf7,0x18,0xbd,0x97,0xdd,0x9d,0x99,0x3e,0x36},
+    {0xc4,0x1f,0xee,0x35,0xc1,0x43,0xa8,0x96,0xcf,0xc8,0xe4,0x08,0x55,0xb3,0x6e,0x97,0x30,0xd3,0x8c,0xb5,0x01,0x68,0x2f,0xb4,0x2b,0x05,0x3a,0x69,0x78,0x9b,0xee,0x48,0xc6,0xae,0x4b,0xe2,0xdc,0x48,0x18,0x2f,0x60,0xaf,0xbc,0xba,0x55,0x72,0x9b,0x76,0x31,0xe9,0xef,0x3c,0x6e,0x3c,0xcb,0x90,0x55,0xb3,0xf9,0xc6,0x9b,0x97,0x1f,0x23,0xc6,0xf3,0x2a,0xcc,0x4b,0xde,0x31,0x5c,0x1f,0x8d,0x20,0xfe,0x30,0xb0,0x4b,0xb0,0x66,0xb4,0x4f,0xc1,0x09,0x70,0x8d,0xb7,0x13,0x24,0x79,0x08,0x9b,0xfa,0x9b,0x07},
+    {0xf4,0x0d,0x30,0xda,0x51,0x3a,0x90,0xe3,0xb0,0x5a,0xa9,0x3d,0x23,0x64,0x39,0x84,0x80,0x64,0x35,0x0b,0x2d,0xf1,0x3c,0xed,0x94,0x71,0x81,0x84,0xf6,0x77,0x8c,0x03,0x45,0x42,0xd5,0xa2,0x80,0xed,0xc9,0xf3,0x52,0x39,0xf6,0x77,0x78,0x8b,0xa0,0x0a,0x75,0x54,0x08,0xd1,0x63,0xac,0x6d,0xd7,0x6b,0x63,0x70,0x94,0x15,0xfb,0xf4,0x1e,0xec,0x7b,0x16,0x5b,0xe6,0x5e,0x4e,0x85,0xc2,0xcd,0xd0,0x96,0x42,0x0a,0x59,0x59,0x99,0x21,0x10,0x98,0x34,0xdf,0xb2,0x72,0x56,0xff,0x0b,0x4a,0x2a,0xe9,0x5e,0x57},
+    {0xcf,0x2f,0x18,0x8a,0x90,0x80,0xc0,0xd4,0xbd,0x9d,0x48,0x99,0xc2,0x70,0xe1,0x30,0xde,0x33,0xf7,0x52,0x57,0xbd,0xba,0x05,0x00,0xfd,0xd3,0x2c,0x11,0xe7,0xd4,0x43,0x01,0xd8,0xa4,0x0a,0x45,0xbc,0x46,0x5d,0xd8,0xb9,0x33,0xa5,0x27,0x12,0xaf,0xc3,0xc2,0x06,0x89,0x2b,0x26,0x3b,0x9e,0x38,0x1b,0x58,0x2f,0x38,0x7e,0x1e,0x0a,0x20,0xc5,0x3a,0xf9,0xea,0x67,0xb9,0x8d,0x51,0xc0,0x52,0x66,0x05,0x9b,0x98,0xbc,0x71,0xf5,0x97,0x71,0x56,0xd9,0x85,0x2b,0xfe,0x38,0x4e,0x1e,0x65,0x52,0xca,0x0e,0x05},
+    {0x9c,0x0c,0x3f,0x45,0xde,0x1a,0x43,0xc3,0x9b,0x3b,0x70,0xff,0x5e,0x04,0xf5,0xe9,0x3d,0x7b,0x84,0xed,0xc9,0x7a,0xd9,0xfc,0xc6,0xf4,0x58,0x1c,0xc2,0xe6,0x0e,0x4b,0xea,0x68,0xe6,0x60,0x76,0x39,0xac,0x97,0x97,0xb4,0x3a,0x15,0xfe,0xbb,0x19,0x9b,0x9f,0xa7,0xec,0x34,0xb5,0x79,0xb1,0x4c,0x57,0xae,0x31,0xa1,0x9f,0xc0,0x51,0x61,0x96,0x5d,0xf0,0xfd,0x0d,0x5c,0xf5,0x3a,0x7a,0xee,0xb4,0x2a,0xe0,0x2e,0x26,0xdd,0x09,0x17,0x17,0x12,0x87,0xbb,0xb2,0x11,0x0b,0x03,0x0f,0x80,0xfa,0x24,0xef,0x1f},
+    {0x96,0x31,0xa7,0x1a,0xfb,0x53,0xd6,0x37,0x18,0x64,0xd7,0x3f,0x30,0x95,0x94,0x0f,0xb2,0x17,0x3a,0xfb,0x09,0x0b,0x20,0xad,0x3e,0x61,0xc8,0x2f,0x29,0x49,0x4d,0x54,0x86,0x6b,0x97,0x30,0xf5,0xaf,0xd2,0x22,0x04,0x46,0xd2,0xc2,0x06,0xb8,0x90,0x8d,0xe5,0xba,0xe5,0x4d,0x6c,0x89,0xa1,0xdc,0x17,0x0c,0x34,0xc8,0xe6,0x5f,0x00,0x28,0x88,0x86,0x52,0x34,0x9f,0xba,0xef,0x6a,0xa1,0x7d,0x10,0x25,0x94,0xff,0x1b,0x5c,0x36,0x4b,0xd9,0x66,0xcd,0xbb,0x5b,0xf7,0xfa,0x6d,0x31,0x0f,0x93,0x72,0xe4,0x72},
+    {0x4f,0x08,0x81,0x97,0x8c,0x20,0x95,0x26,0xe1,0x0e,0x45,0x23,0x0b,0x2a,0x50,0xb1,0x02,0xde,0xef,0x03,0xa6,0xae,0x9d,0xfd,0x4c,0xa3,0x33,0x27,0x8c,0x2e,0x9d,0x5a,0x27,0x76,0x2a,0xd3,0x35,0xf6,0xf3,0x07,0xf0,0x66,0x65,0x5f,0x86,0x4d,0xaa,0x7a,0x50,0x44,0xd0,0x28,0x97,0xe7,0x85,0x3c,0x38,0x64,0xe0,0x0f,0x00,0x7f,0xee,0x1f,0xe5,0xf7,0xdb,0x03,0xda,0x05,0x53,0x76,0xbd,0xcd,0x34,0x14,0x49,0xf2,0xda,0xa4,0xec,0x88,0x4a,0xd2,0xcd,0xd5,0x4a,0x7b,0x43,0x05,0x04,0xee,0x51,0x40,0xf9,0x00},
+    {0xb2,0x30,0xd3,0xc3,0x23,0x6b,0x35,0x8d,0x06,0x1b,0x47,0xb0,0x9b,0x8b,0x1c,0xf2,0x3c,0xb8,0x42,0x6e,0x6c,0x31,0x6c,0xb3,0x0d,0xb1,0xea,0x8b,0x7e,0x9c,0xd7,0x07,0x53,0x97,0xaf,0x07,0xbb,0x93,0xef,0xd7,0xa7,0x66,0xb7,0x3d,0xcf,0xd0,0x3e,0x58,0xc5,0x1e,0x0b,0x6e,0xbf,0x98,0x69,0xce,0x52,0x04,0xd4,0x5d,0xd2,0xff,0xb7,0x47,0x12,0xdd,0x08,0xbc,0x9c,0xfb,0xfb,0x87,0x9b,0xc2,0xee,0xe1,0x3a,0x6b,0x06,0x8a,0xbf,0xc1,0x1f,0xdb,0x2b,0x24,0x57,0x0d,0xb6,0x4b,0xa6,0x5e,0xa3,0x20,0x35,0x1c},
+    {0x4a,0xa3,0xcb,0xbc,0xa6,0x53,0xd2,0x80,0x9b,0x21,0x38,0x38,0xa1,0xc3,0x61,0x3e,0x96,0xe3,0x82,0x98,0x01,0xb6,0xc3,0x90,0x6f,0xe6,0x0e,0x5d,0x77,0x05,0x3d,0x1c,0x59,0xc0,0x6b,0x21,0x40,0x6f,0xa8,0xcd,0x7e,0xd8,0xbc,0x12,0x1d,0x23,0xbb,0x1f,0x90,0x09,0xc7,0x17,0x9e,0x6a,0x95,0xb4,0x55,0x2e,0xd1,0x66,0x3b,0x0c,0x75,0x38,0x1a,0xe5,0x22,0x94,0x40,0xf1,0x2e,0x69,0x71,0xf6,0x5d,0x2b,0x3c,0xc7,0xc0,0xcb,0x29,0xe0,0x4c,0x74,0xe7,0x4f,0x01,0x21,0x7c,0x48,0x30,0xd3,0xc7,0xe2,0x21,0x06},
+    {0x8d,0x83,0x59,0x82,0xcc,0x60,0x98,0xaf,0xdc,0x9a,0x9f,0xc6,0xc1,0x48,0xea,0x90,0x30,0x1e,0x58,0x65,0x37,0x48,0x26,0x65,0xbc,0xa5,0xd3,0x7b,0x09,0xd6,0x07,0x00,0xf3,0xf0,0xdb,0xb0,0x96,0x17,0xae,0xb7,0x96,0xe1,0x7c,0xe1,0xb9,0xaf,0xdf,0x54,0xb4,0xa3,0xaa,0xe9,0x71,0x30,0x92,0x25,0x9d,0x2e,0x00,0xa1,0x9c,0x58,0x8e,0x5d,0x4b,0xa9,0x42,0x08,0x95,0x1d,0xbf,0xc0,0x3e,0x2e,0x8f,0x58,0x63,0xc3,0xd3,0xb2,0xef,0xe2,0x51,0xbb,0x38,0x14,0x96,0x0a,0x86,0xbf,0x1c,0x3c,0x78,0xd7,0x83,0x15},
+    {0xe1,0x7a,0xa2,0x5d,0xef,0xa2,0xee,0xec,0x74,0x01,0x67,0x55,0x14,0x3a,0x7c,0x59,0x7a,0x16,0x09,0x66,0x12,0x2a,0xa6,0xc9,0x70,0x8f,0xed,0x81,0x2e,0x5f,0x2a,0x25,0xc7,0x28,0x9d,0xcc,0x04,0x47,0x03,0x90,0x8f,0xc5,0x2c,0xf7,0x9e,0x67,0x1b,0x1d,0x26,0x87,0x5b,0xbe,0x5f,0x2b,0xe1,0x16,0x0a,0x58,0xc5,0x83,0x4e,0x06,0x58,0x49,0x0d,0xe8,0x66,0x50,0x26,0x94,0x28,0x0d,0x6b,0x8c,0x7c,0x30,0x85,0xf7,0xc3,0xfc,0xfd,0x12,0x11,0x0c,0x78,0xda,0x53,0x1b,0x88,0xb3,0x43,0xd8,0x0b,0x17,0x9c,0x07},
+    {0xff,0x6f,0xfa,0x64,0xe4,0xec,0x06,0x05,0x23,0xe5,0x05,0x62,0x1e,0x43,0xe3,0xbe,0x42,0xea,0xb8,0x51,0x24,0x42,0x79,0x35,0x00,0xfb,0xc9,0x4a,0xe3,0x05,0xec,0x6d,0x56,0xd0,0xd5,0xc0,0x50,0xcd,0xd6,0xcd,0x3b,0x57,0x03,0xbb,0x6d,0x68,0xf7,0x9a,0x48,0xef,0xc3,0xf3,0x3f,0x72,0xa6,0x3c,0xcc,0x8a,0x7b,0x31,0xd7,0xc0,0x68,0x67,0xb3,0xc1,0x55,0xf1,0xe5,0x25,0xb6,0x94,0x91,0x7b,0x7b,0x99,0xa7,0xf3,0x7b,0x41,0x00,0x26,0x6b,0x6d,0xdc,0xbd,0x2c,0xc2,0xf4,0x52,0xcd,0xdd,0x14,0x5e,0x44,0x51},
+    {0x51,0x49,0x14,0x3b,0x4b,0x2b,0x50,0x57,0xb3,0xbc,0x4b,0x44,0x6b,0xff,0x67,0x8e,0xdb,0x85,0x63,0x16,0x27,0x69,0xbd,0xb8,0xc8,0x95,0x92,0xe3,0x31,0x6f,0x18,0x13,0x55,0xa4,0xbe,0x2b,0xab,0x47,0x31,0x89,0x29,0x91,0x07,0x92,0x4f,0xa2,0x53,0x8c,0xa7,0xf7,0x30,0xbe,0x48,0xf9,0x49,0x4b,0x3d,0xd4,0x4f,0x6e,0x08,0x90,0xe9,0x12,0x2e,0xbb,0xdf,0x7f,0xb3,0x96,0x0c,0xf1,0xf9,0xea,0x1c,0x12,0x5e,0x93,0x9a,0x9f,0x3f,0x98,0x5b,0x3a,0xc4,0x36,0x11,0xdf,0xaf,0x99,0x3e,0x5d,0xf0,0xe3,0xb2,0x77},
+    {0xde,0xc4,0x2e,0x9c,0xc5,0xa9,0x6f,0x29,0xcb,0xf3,0x84,0x4f,0xbf,0x61,0x8b,0xbc,0x08,0xf9,0xa8,0x17,0xd9,0x06,0x77,0x1c,0x5d,0x25,0xd3,0x7a,0xfc,0x95,0xb7,0x63,0xa4,0xb0,0xdd,0x12,0x9c,0x63,0x98,0xd5,0x6b,0x86,0x24,0xc0,0x30,0x9f,0xd1,0xa5,0x60,0xe4,0xfc,0x58,0x03,0x2f,0x7c,0xd1,0x8a,0x5e,0x09,0x2e,0x15,0x95,0xa1,0x07,0xc8,0x5f,0x9e,0x38,0x02,0x8f,0x36,0xa8,0x3b,0xe4,0x8d,0xcf,0x02,0x3b,0x43,0x90,0x43,0x26,0x41,0xc5,0x5d,0xfd,0xa1,0xaf,0x37,0x01,0x2f,0x03,0x3d,0xe8,0x8f,0x3e},
+    {0x94,0xa2,0x70,0x05,0xb9,0x15,0x8b,0x2f,0x49,0x45,0x08,0x67,0x70,0x42,0xf2,0x94,0x84,0xfd,0xbb,0x61,0xe1,0x5a,0x1c,0xde,0x07,0x40,0xac,0x7f,0x79,0x3b,0xba,0x75,0x3c,0xd1,0xef,0xe8,0x8d,0x4c,0x70,0x08,0x31,0x37,0xe0,0x33,0x8e,0x1a,0xc5,0xdf,0xe3,0xcd,0x60,0x12,0xa5,0x5d,0x9d,0xa5,0x86,0x8c,0x25,0xa6,0x99,0x08,0xd6,0x22,0x96,0xd1,0xcd,0x70,0xc0,0xdb,0x39,0x62,0x9a,0x8a,0x7d,0x6c,0x8b,0x8a,0xfe,0x60,0x60,0x12,0x40,0xeb,0xbc,0x47,0x88,0xb3,0x5e,0x9e,0x77,0x87,0x7b,0xd0,0x04,0x09},
+    {0x9c,0x91,0xba,0xdd,0xd4,0x1f,0xce,0xb4,0xaa,0x8d,0x4c,0xc7,0x3e,0xdb,0x31,0xcf,0x51,0xcc,0x86,0xad,0x63,0xcc,0x63,0x2c,0x07,0xde,0x1d,0xbc,0x3f,0x14,0xe2,0x43,0xb9,0x40,0xf9,0x48,0x66,0x2d,0x32,0xf4,0x39,0x0c,0x2d,0xbd,0x0c,0x2f,0x95,0x06,0x31,0xf9,0x81,0xa0,0xad,0x97,0x76,0x16,0x6c,0x2a,0xf7,0xba,0xce,0xaa,0x40,0x62,0xa0,0x95,0xa2,0x5b,0x9c,0x74,0x34,0xf8,0x5a,0xd2,0x37,0xca,0x5b,0x7c,0x94,0xd6,0x6a,0x31,0xc9,0xe7,0xa7,0x3b,0xf1,0x66,0xac,0x0c,0xb4,0x8d,0x23,0xaf,0xbd,0x56},
+    {0xeb,0x33,0x35,0xf5,0xe3,0xb9,0x2a,0x36,0x40,0x3d,0xb9,0x6e,0xd5,0x68,0x85,0x33,0x72,0x55,0x5a,0x1d,0x52,0x14,0x0e,0x9e,0x18,0x13,0x74,0x83,0x6d,0xa8,0x24,0x1d,0xb2,0x3b,0x9d,0xc1,0x6c,0xd3,0x10,0x13,0xb9,0x86,0x23,0x62,0xb7,0x6b,0x2a,0x06,0x5c,0x4f,0xa1,0xd7,0x91,0x85,0x9b,0x7c,0x54,0x57,0x1e,0x7e,0x50,0x31,0xaa,0x03,0x1f,0xce,0xd4,0xff,0x48,0x76,0xec,0xf4,0x1c,0x8c,0xac,0x54,0xf0,0xea,0x45,0xe0,0x7c,0x35,0x09,0x1d,0x82,0x25,0xd2,0x88,0x59,0x48,0xeb,0x9a,0xdc,0x61,0xb2,0x43},
+    {0xbb,0x79,0xbb,0x88,0x19,0x1e,0x5b,0xe5,0x9d,0x35,0x7a,0xc1,0x7d,0xd0,0x9e,0xa0,0x33,0xea,0x3d,0x60,0xe2,0x2e,0x2c,0xb0,0xc2,0x6b,0x27,0x5b,0xcf,0x55,0x60,0x32,0x64,0x13,0x95,0x6c,0x8b,0x3d,0x51,0x19,0x7b,0xf4,0x0b,0x00,0x26,0x71,0xfe,0x94,0x67,0x95,0x4f,0xd5,0xdd,0x10,0x8d,0x02,0x64,0x09,0x94,0x42,0xe2,0xd5,0xb4,0x02,0xf2,0x8d,0xd1,0x28,0xcb,0x55,0xa1,0xb4,0x08,0xe5,0x6c,0x18,0x46,0x46,0xcc,0xea,0x89,0x43,0x82,0x6c,0x93,0xf4,0x9c,0xc4,0x10,0x34,0x5d,0xae,0x09,0xc8,0xa6,0x27},
+    {0x88,0xb1,0x0d,0x1f,0xcd,0xeb,0xa6,0x8b,0xe8,0x5b,0x5a,0x67,0x3a,0xd7,0xd3,0x37,0x5a,0x58,0xf5,0x15,0xa3,0xdf,0x2e,0xf2,0x7e,0xa1,0x60,0xff,0x74,0x71,0xb6,0x2c,0x54,0x69,0x3d,0xc4,0x0a,0x27,0x2c,0xcd,0xb2,0xca,0x66,0x6a,0x57,0x3e,0x4a,0xdd,0x6c,0x03,0xd7,0x69,0x24,0x59,0xfa,0x79,0x99,0x25,0x8c,0x3d,0x60,0x03,0x15,0x22,0xd0,0xe1,0x0b,0x39,0xf9,0xcd,0xee,0x59,0xf1,0xe3,0x8c,0x72,0x44,0x20,0x42,0xa9,0xf4,0xf0,0x94,0x7a,0x66,0x1c,0x89,0x82,0x36,0xf4,0x90,0x38,0xb7,0xf4,0x1d,0x7b},
+    {0x24,0xa2,0xb2,0xb3,0xe0,0xf2,0x92,0xe4,0x60,0x11,0x55,0x2b,0x06,0x9e,0x6c,0x7c,0x0e,0x7b,0x7f,0x0d,0xe2,0x8f,0xeb,0x15,0x92,0x59,0xfc,0x58,0x26,0xef,0xfc,0x61,0x8c,0xf5,0xf8,0x07,0x18,0x22,0x2e,0x5f,0xd4,0x09,0x94,0xd4,0x9f,0x5c,0x55,0xe3,0x30,0xa6,0xb6,0x1f,0x8d,0xa8,0xaa,0xb2,0x3d,0xe0,0x52,0xd3,0x45,0x82,0x69,0x68,0x7a,0x18,0x18,0x2a,0x85,0x5d,0xb1,0xdb,0xd7,0xac,0xdd,0x86,0xd3,0xaa,0xe4,0xf3,0x82,0xc4,0xf6,0x0f,0x81,0xe2,0xba,0x44,0xcf,0x01,0xaf,0x3d,0x47,0x4c,0xcf,0x46},
+    {0xf9,0xe5,0xc4,0x9e,0xed,0x25,0x65,0x42,0x03,0x33,0x90,0x16,0x01,0xda,0x5e,0x0e,0xdc,0xca,0xe5,0xcb,0xf2,0xa7,0xb1,0x72,0x40,0x5f,0xeb,0x14,0xcd,0x7b,0x38,0x29,0x40,0x81,0x49,0xf1,0xa7,0x6e,0x3c,0x21,0x54,0x48,0x2b,0x39,0xf8,0x7e,0x1e,0x7c,0xba,0xce,0x29,0x56,0x8c,0xc3,0x88,0x24,0xbb,0xc5,0x8c,0x0d,0xe5,0xaa,0x65,0x10,0x57,0x0d,0x20,0xdf,0x25,0x45,0x2c,0x1c,0x4a,0x67,0xca,0xbf,0xd6,0x2d,0x3b,0x5c,0x30,0x40,0x83,0xe1,0xb1,0xe7,0x07,0x0a,0x16,0xe7,0x1c,0x4f,0xe6,0x98,0xa1,0x69},
+    {0xbc,0x78,0x1a,0xd9,0xe0,0xb2,0x62,0x90,0x67,0x96,0x50,0xc8,0x9c,0x88,0xc9,0x47,0xb8,0x70,0x50,0x40,0x66,0x4a,0xf5,0x9d,0xbf,0xa1,0x93,0x24,0xa9,0xe6,0x69,0x73,0xed,0xca,0xc5,0xdc,0x34,0x44,0x01,0xe1,0x33,0xfb,0x84,0x3c,0x96,0x5d,0xed,0x47,0xe7,0xa0,0x86,0xed,0x76,0x95,0x01,0x70,0xe4,0xf9,0x67,0xd2,0x7b,0x69,0xb2,0x25,0x64,0x68,0x98,0x13,0xfb,0x3f,0x67,0x9d,0xb8,0xc7,0x5d,0x41,0xd9,0xfb,0xa5,0x3c,0x5e,0x3b,0x27,0xdf,0x3b,0xcc,0x4e,0xe0,0xd2,0x4c,0x4e,0xb5,0x3d,0x68,0x20,0x14},
+    {0x97,0xd1,0x9d,0x24,0x1e,0xbd,0x78,0xb4,0x02,0xc1,0x58,0x5e,0x00,0x35,0x0c,0x62,0x5c,0xac,0xba,0xcc,0x2f,0xd3,0x02,0xfb,0x2d,0xa7,0x08,0xf5,0xeb,0x3b,0xb6,0x60,0xd0,0x5a,0xcc,0xc1,0x6f,0xbb,0xee,0x34,0x8b,0xac,0x46,0x96,0xe9,0x0c,0x1b,0x6a,0x53,0xde,0x6b,0xa6,0x49,0xda,0xb0,0xd3,0xc1,0x81,0xd0,0x61,0x41,0x3b,0xe8,0x31,0x4f,0x2b,0x06,0x9e,0x12,0xc7,0xe8,0x97,0xd8,0x0a,0x32,0x29,0x4f,0x8f,0xe4,0x49,0x3f,0x68,0x18,0x6f,0x4b,0xe1,0xec,0x5b,0x17,0x03,0x55,0x2d,0xb6,0x1e,0xcf,0x55},
+    {0x58,0x3d,0xc2,0x65,0x10,0x10,0x79,0x58,0x9c,0x81,0x94,0x50,0x6d,0x08,0x9d,0x8b,0xa7,0x5f,0xc5,0x12,0xa9,0x2f,0x40,0xe2,0xd4,0x91,0x08,0x57,0x64,0x65,0x9a,0x66,0x52,0x8c,0xf5,0x7d,0xe3,0xb5,0x76,0x30,0x36,0xcc,0x99,0xe7,0xdd,0xb9,0x3a,0xd7,0x20,0xee,0x13,0x49,0xe3,0x1c,0x83,0xbd,0x33,0x01,0xba,0x62,0xaa,0xfb,0x56,0x1a,0xec,0xc9,0x9d,0x5c,0x50,0x6b,0x3e,0x94,0x1a,0x37,0x7c,0xa7,0xbb,0x57,0x25,0x30,0x51,0x76,0x34,0x41,0x56,0xae,0x73,0x98,0x5c,0x8a,0xc5,0x99,0x67,0x83,0xc4,0x13},
+    {0xb9,0xe1,0xb3,0x5a,0x46,0x5d,0x3a,0x42,0x61,0x3f,0xf1,0xc7,0x87,0xc1,0x13,0xfc,0xb6,0xb9,0xb5,0xec,0x64,0x36,0xf8,0x19,0x07,0xb6,0x37,0xa6,0x93,0x0c,0xf8,0x66,0x80,0xd0,0x8b,0x5d,0x6a,0xfb,0xdc,0xc4,0x42,0x48,0x1a,0x57,0xec,0xc4,0xeb,0xde,0x65,0x53,0xe5,0xb8,0x83,0xe8,0xb2,0xd4,0x27,0xb8,0xe5,0xc8,0x7d,0xc8,0xbd,0x50,0x11,0xe1,0xdf,0x6e,0x83,0x37,0x6d,0x60,0xd9,0xab,0x11,0xf0,0x15,0x3e,0x35,0x32,0x96,0x3b,0xb7,0x25,0xc3,0x3a,0xb0,0x64,0xae,0xd5,0x5f,0x72,0x44,0x64,0xd5,0x1d},
+    {0x7d,0x12,0x62,0x33,0xf8,0x7f,0xa4,0x8f,0x15,0x7c,0xcd,0x71,0xc4,0x6a,0x9f,0xbc,0x8b,0x0c,0x22,0x49,0x43,0x45,0x71,0x6e,0x2e,0x73,0x9f,0x21,0x12,0x59,0x64,0x0e,0x9a,0xc8,0xba,0x08,0x00,0xe6,0x97,0xc2,0xe0,0xc3,0xe1,0xea,0x11,0xea,0x4c,0x7d,0x7c,0x97,0xe7,0x9f,0xe1,0x8b,0xe3,0xf3,0xcd,0x05,0xa3,0x63,0x0f,0x45,0x3a,0x3a,0x27,0x46,0x39,0xd8,0x31,0x2f,0x8f,0x07,0x10,0xa5,0x94,0xde,0x83,0x31,0x9d,0x38,0x80,0x6f,0x99,0x17,0x6d,0x6c,0xe3,0xd1,0x7b,0xa8,0xa9,0x93,0x93,0x8d,0x8c,0x31},
+    {0x19,0xfe,0xff,0x2a,0x03,0x5d,0x74,0xf2,0x66,0xdb,0x24,0x7f,0x49,0x3c,0x9f,0x0c,0xef,0x98,0x85,0xba,0xe3,0xd3,0x98,0xbc,0x14,0x53,0x1d,0x9a,0x67,0x7c,0x4c,0x22,0x98,0xd3,0x1d,0xab,0x29,0x9e,0x66,0x5d,0x3b,0x9e,0x2d,0x34,0x58,0x16,0x92,0xfc,0xcd,0x73,0x59,0xf3,0xfd,0x1d,0x85,0x55,0xf6,0x0a,0x95,0x25,0xc3,0x41,0x9a,0x50,0xe9,0x25,0xf9,0xa6,0xdc,0x6e,0xc0,0xbd,0x33,0x1f,0x1b,0x64,0xf4,0xf3,0x3e,0x79,0x89,0x3e,0x83,0x9d,0x80,0x12,0xec,0x82,0x89,0x13,0xa1,0x28,0x23,0xf0,0xbf,0x05},
+    {0x0b,0xe0,0xca,0x23,0x70,0x13,0x32,0x36,0x59,0xcf,0xac,0xd1,0x0a,0xcf,0x4a,0x54,0x88,0x1c,0x1a,0xd2,0x49,0x10,0x74,0x96,0xa7,0x44,0x2a,0xfa,0xc3,0x8c,0x0b,0x78,0xe4,0x12,0xc5,0x0d,0xdd,0xa0,0x81,0x68,0xfe,0xfa,0xa5,0x44,0xc8,0x0d,0xe7,0x4f,0x40,0x52,0x4a,0x8f,0x6b,0x8e,0x74,0x1f,0xea,0xa3,0x01,0xee,0xcd,0x77,0x62,0x57,0x5f,0x30,0x4f,0x23,0xbc,0x8a,0xf3,0x1e,0x08,0xde,0x05,0x14,0xbd,0x7f,0x57,0x9a,0x0d,0x2a,0xe6,0x34,0x14,0xa5,0x82,0x5e,0xa1,0xb7,0x71,0x62,0x72,0x18,0xf4,0x5f},
+    {0x9d,0xdb,0x89,0x17,0x0c,0x08,0x8e,0x39,0xf5,0x78,0xe7,0xf3,0x25,0x20,0x60,0xa7,0x5d,0x03,0xbd,0x06,0x4c,0x89,0x98,0xfa,0xbe,0x66,0xa9,0x25,0xdc,0x03,0x6a,0x10,0x40,0x95,0xb6,0x13,0xe8,0x47,0xdb,0xe5,0xe1,0x10,0x26,0x43,0x3b,0x2a,0x5d,0xf3,0x76,0x12,0x78,0x38,0xe9,0x26,0x1f,0xac,0x69,0xcb,0xa0,0xa0,0x8c,0xdb,0xd4,0x29,0xd0,0x53,0x33,0x33,0xaf,0x0a,0xad,0xd9,0xe5,0x09,0xd3,0xac,0xa5,0x9d,0x66,0x38,0xf0,0xf7,0x88,0xc8,0x8a,0x65,0x57,0x3c,0xfa,0xbe,0x2c,0x05,0x51,0x8a,0xb3,0x4a},
+    {0x93,0xd5,0x68,0x67,0x25,0x2b,0x7c,0xda,0x13,0xca,0x22,0x44,0x57,0xc0,0xc1,0x98,0x1d,0xce,0x0a,0xca,0xd5,0x0b,0xa8,0xf1,0x90,0xa6,0x88,0xc0,0xad,0xd1,0xcd,0x29,0x9c,0xc0,0xdd,0x5f,0xef,0xd1,0xcf,0xd6,0xce,0x5d,0x57,0xf7,0xfd,0x3e,0x2b,0xe8,0xc2,0x34,0x16,0x20,0x5d,0x6b,0xd5,0x25,0x9b,0x2b,0xed,0x04,0xbb,0xc6,0x41,0x30,0x48,0xe1,0x56,0xd9,0xf9,0xf2,0xf2,0x0f,0x2e,0x6b,0x35,0x9f,0x75,0x97,0xe7,0xad,0x5c,0x02,0x6c,0x5f,0xbb,0x98,0x46,0x1a,0x7b,0x9a,0x04,0x14,0x68,0xbd,0x4b,0x10},
+    {0x67,0xed,0xf1,0x68,0x31,0xfd,0xf0,0x51,0xc2,0x3b,0x6f,0xd8,0xcd,0x1d,0x81,0x2c,0xde,0xf2,0xd2,0x04,0x43,0x5c,0xdc,0x44,0x49,0x71,0x2a,0x09,0x57,0xcc,0xe8,0x5b,0x63,0xf1,0x7f,0xd6,0x5f,0x9a,0x5d,0xa9,0x81,0x56,0xc7,0x4c,0x9d,0xe6,0x2b,0xe9,0x57,0xf2,0x20,0xde,0x4c,0x02,0xf8,0xb7,0xf5,0x2d,0x07,0xfb,0x20,0x2a,0x4f,0x20,0x79,0xb0,0xeb,0x30,0x3d,0x3b,0x14,0xc8,0x30,0x2e,0x65,0xbd,0x5a,0x15,0x89,0x75,0x31,0x5c,0x6d,0x8f,0x31,0x3c,0x3c,0x65,0x1f,0x16,0x79,0xc2,0x17,0xfb,0x70,0x25},
+    {0x75,0x15,0xb6,0x2c,0x7f,0x36,0xfa,0x3e,0x6c,0x02,0xd6,0x1c,0x76,0x6f,0xf9,0xf5,0x62,0x25,0xb5,0x65,0x2a,0x14,0xc7,0xe8,0xcd,0x0a,0x03,0x53,0xea,0x65,0xcb,0x3d,0x5a,0x24,0xb8,0x0b,0x55,0xa9,0x2e,0x19,0xd1,0x50,0x90,0x8f,0xa8,0xfb,0xe6,0xc8,0x35,0xc9,0xa4,0x88,0x2d,0xea,0x86,0x79,0x68,0x86,0x01,0xde,0x91,0x5f,0x1c,0x24,0xaa,0x6c,0xde,0x40,0x29,0x17,0xd8,0x28,0x3a,0x73,0xd9,0x22,0xf0,0x2c,0xbf,0x8f,0xd1,0x01,0x5b,0x23,0xdd,0xfc,0xd7,0x16,0xe5,0xf0,0xcd,0x5f,0xdd,0x0e,0x42,0x08},
+    {0x4a,0xfa,0x62,0x83,0xab,0x20,0xff,0xcd,0x6e,0x3e,0x1a,0xe2,0xd4,0x18,0xe1,0x57,0x2b,0xe6,0x39,0xfc,0x17,0x96,0x17,0xe3,0xfd,0x69,0x17,0xbc,0xef,0x53,0x9a,0x0d,0xce,0x10,0xf4,0x04,0x4e,0xc3,0x58,0x03,0x85,0x06,0x6e,0x27,0x5a,0x5b,0x13,0xb6,0x21,0x15,0xb9,0xeb,0xc7,0x70,0x96,0x5d,0x9c,0x88,0xdb,0x21,0xf3,0x54,0xd6,0x04,0xd5,0xb5,0xbd,0xdd,0x16,0xc1,0x7d,0x5e,0x2d,0xdd,0xa5,0x8d,0xb6,0xde,0x54,0x29,0x92,0xa2,0x34,0x33,0x17,0x08,0xb6,0x1c,0xd7,0x1a,0x99,0x18,0x26,0x4f,0x7a,0x4a},
+    {0x95,0x5f,0xb1,0x5f,0x02,0x18,0xa7,0xf4,0x8f,0x1b,0x5c,0x6b,0x34,0x5f,0xf6,0x3d,0x12,0x11,0xe0,0x00,0x85,0xf0,0xfc,0xcd,0x48,0x18,0xd3,0xdd,0x4c,0x0c,0xb5,0x11,0x4b,0x2a,0x37,0xaf,0x91,0xb2,0xc3,0x24,0xf2,0x47,0x81,0x71,0x70,0x82,0xda,0x93,0xf2,0x9e,0x89,0x86,0x64,0x85,0x84,0xdd,0x33,0xee,0xe0,0x23,0x42,0x31,0x96,0x4a,0xd6,0xff,0xa4,0x08,0x44,0x27,0xe8,0xa6,0xd9,0x76,0x15,0x9c,0x7e,0x17,0x8e,0x73,0xf2,0xb3,0x02,0x3d,0xb6,0x48,0x33,0x77,0x51,0xcc,0x6b,0xce,0x4d,0xce,0x4b,0x4f},
+    {0x84,0x25,0x24,0xe2,0x5a,0xce,0x1f,0xa7,0x9e,0x8a,0xf5,0x92,0x56,0x72,0xea,0x26,0xf4,0x3c,0xea,0x1c,0xd7,0x09,0x1a,0xd2,0xe6,0x01,0x1c,0xb7,0x14,0xdd,0xfc,0x73,0x6f,0x0b,0x9d,0xc4,0x6e,0x61,0xe2,0x30,0x17,0x23,0xec,0xca,0x8f,0x71,0x56,0xe4,0xa6,0x4f,0x6b,0xf2,0x9b,0x40,0xeb,0x48,0x37,0x5f,0x59,0x61,0xe5,0xce,0x42,0x30,0x41,0xac,0x9b,0x44,0x79,0x70,0x7e,0x42,0x0a,0x31,0xe2,0xbc,0x6d,0xe3,0x5a,0x85,0x7c,0x1a,0x84,0x5f,0x21,0x76,0xae,0x4c,0xd6,0xe1,0x9c,0x9a,0x0c,0x74,0x9e,0x38},
+    {0xce,0xb9,0xdc,0x34,0xae,0xb3,0xfc,0x64,0xad,0xd0,0x48,0xe3,0x23,0x03,0x50,0x97,0x1b,0x38,0xc6,0x62,0x7d,0xf0,0xb3,0x45,0x88,0x67,0x5a,0x46,0x79,0x53,0x54,0x61,0x28,0xac,0x0e,0x57,0xf6,0x78,0xbd,0xc9,0xe1,0x9c,0x91,0x27,0x32,0x0b,0x5b,0xe5,0xed,0x91,0x9b,0xa1,0xab,0x3e,0xfc,0x65,0x90,0x36,0x26,0xd6,0xe5,0x25,0xc4,0x25,0x6e,0xde,0xd7,0xf1,0xa6,0x06,0x3e,0x3f,0x08,0x23,0x06,0x8e,0x27,0x76,0xf9,0x3e,0x77,0x6c,0x8a,0x4e,0x26,0xf6,0x14,0x8c,0x59,0x47,0x48,0x15,0x89,0xa0,0x39,0x65},
+    {0x73,0xf7,0xd2,0xc3,0x74,0x1f,0xd2,0xe9,0x45,0x68,0xc4,0x25,0x41,0x54,0x50,0xc1,0x33,0x9e,0xb9,0xf9,0xe8,0x5c,0x4e,0x62,0x6c,0x18,0xcd,0xc5,0xaa,0xe4,0xc5,0x11,0x19,0x4a,0xbb,0x14,0xd4,0xdb,0xc4,0xdd,0x8e,0x4f,0x42,0x98,0x3c,0xbc,0xb2,0x19,0x69,0x71,0xca,0x36,0xd7,0x9f,0xa8,0x48,0x90,0xbd,0x19,0xf0,0x0e,0x32,0x65,0x0f,0xc6,0xe0,0xfd,0xca,0xb1,0xd1,0x86,0xd4,0x81,0x51,0x3b,0x16,0xe3,0xe6,0x3f,0x4f,0x9a,0x93,0xf2,0xfa,0x0d,0xaf,0xa8,0x59,0x2a,0x07,0x33,0xec,0xbd,0xc7,0xab,0x4c},
+    {0x2e,0x0a,0x9c,0x08,0x24,0x96,0x9e,0x23,0x38,0x47,0xfe,0x3a,0xc0,0xc4,0x48,0xc7,0x2a,0xa1,0x4f,0x76,0x2a,0xed,0xdb,0x17,0x82,0x85,0x1c,0x32,0xf0,0x93,0x9b,0x63,0x89,0xd2,0x78,0x3f,0x8f,0x78,0x8f,0xc0,0x9f,0x4d,0x40,0xa1,0x2c,0xa7,0x30,0xfe,0x9d,0xcc,0x65,0xcf,0xfc,0x8b,0x77,0xf2,0x21,0x20,0xcb,0x5a,0x16,0x98,0xe4,0x7e,0xc3,0xa1,0x11,0x91,0xe3,0x08,0xd5,0x7b,0x89,0x74,0x90,0x80,0xd4,0x90,0x2b,0x2b,0x19,0xfd,0x72,0xae,0xc2,0xae,0xd2,0xe7,0xa6,0x02,0xb6,0x85,0x3c,0x49,0xdf,0x0e},
+    {0x68,0x5a,0x9b,0x59,0x58,0x81,0xcc,0xae,0x0e,0xe2,0xad,0xeb,0x0f,0x4f,0x57,0xea,0x07,0x7f,0xb6,0x22,0x74,0x1d,0xe4,0x4f,0xb4,0x4f,0x9d,0x01,0xe3,0x92,0x3b,0x40,0x13,0x41,0x76,0x84,0xd2,0xc4,0x67,0x67,0x35,0xf8,0xf5,0xf7,0x3f,0x40,0x90,0xa0,0xde,0xbe,0xe6,0xca,0xfa,0xcf,0x8f,0x1c,0x69,0xa3,0xdf,0xd1,0x54,0x0c,0xc0,0x04,0xf8,0x5c,0x46,0x8b,0x81,0x2f,0xc2,0x4d,0xf8,0xef,0x80,0x14,0x5a,0xf3,0xa0,0x71,0x57,0xd6,0xc7,0x04,0xad,0xbf,0xe8,0xae,0xf4,0x76,0x61,0xb2,0x2a,0xb1,0x5b,0x35},
+    {0xf4,0xbb,0x93,0x74,0xcc,0x64,0x1e,0xa7,0xc3,0xb0,0xa3,0xec,0xd9,0x84,0xbd,0xe5,0x85,0xe7,0x05,0xfa,0x0c,0xc5,0x6b,0x0a,0x12,0xc3,0x2e,0x18,0x32,0x81,0x9b,0x0f,0x18,0x73,0x8c,0x5a,0xc7,0xda,0x01,0xa3,0x11,0xaa,0xce,0xb3,0x9d,0x03,0x90,0xed,0x2d,0x3f,0xae,0x3b,0xbf,0x7c,0x07,0x6f,0x8e,0xad,0x52,0xe0,0xf8,0xea,0x18,0x75,0x32,0x6c,0x7f,0x1b,0xc4,0x59,0x88,0xa4,0x98,0x32,0x38,0xf4,0xbc,0x60,0x2d,0x0f,0xd9,0xd1,0xb1,0xc9,0x29,0xa9,0x15,0x18,0xc4,0x55,0x17,0xbb,0x1b,0x87,0xc3,0x47},
+    {0x48,0x4f,0xec,0x71,0x97,0x53,0x44,0x51,0x6e,0x5d,0x8c,0xc9,0x7d,0xb1,0x05,0xf8,0x6b,0xc6,0xc3,0x47,0x1a,0xc1,0x62,0xf7,0xdc,0x99,0x46,0x76,0x85,0x9b,0xb8,0x00,0xb0,0x66,0x50,0xc8,0x50,0x5d,0xe6,0xfb,0xb0,0x99,0xa2,0xb3,0xb0,0xc4,0xec,0x62,0xe0,0xe8,0x1a,0x44,0xea,0x54,0x37,0xe5,0x5f,0x8d,0xd4,0xe8,0x2c,0xa0,0xfe,0x08,0xd0,0xea,0xde,0x68,0x76,0xdd,0x4d,0x82,0x23,0x5d,0x68,0x4b,0x20,0x45,0x64,0xc8,0x65,0xd6,0x89,0x5d,0xcd,0xcf,0x14,0xb5,0x37,0xd5,0x75,0x4f,0xa7,0x29,0x38,0x47},
+    {0x18,0xc4,0x79,0x46,0x75,0xda,0xd2,0x82,0xf0,0x8d,0x61,0xb2,0xd8,0xd7,0x3b,0xe6,0x0a,0xeb,0x47,0xac,0x24,0xef,0x5e,0x35,0xb4,0xc6,0x33,0x48,0x4c,0x68,0x78,0x20,0xc9,0x02,0x39,0xad,0x3a,0x53,0xd9,0x23,0x8f,0x58,0x03,0xef,0xce,0xdd,0xc2,0x64,0xb4,0x2f,0xe1,0xcf,0x90,0x73,0x25,0x15,0x90,0xd3,0xe4,0x44,0x4d,0x8b,0x66,0x6c,0x0c,0x82,0x78,0x7a,0x21,0xcf,0x48,0x3b,0x97,0x3e,0x27,0x81,0xb2,0x0a,0x6a,0xf7,0x7b,0xed,0x8e,0x8c,0xa7,0x65,0x6c,0xa9,0x3f,0x43,0x8a,0x4f,0x05,0xa6,0x11,0x74},
+    {0x6d,0xc8,0x9d,0xb9,0x32,0x9d,0x65,0x4d,0x15,0xf1,0x3a,0x60,0x75,0xdc,0x4c,0x04,0x88,0xe4,0xc2,0xdc,0x2c,0x71,0x4c,0xb3,0xff,0x34,0x81,0xfb,0x74,0x65,0x13,0x7c,0xb4,0x75,0xb1,0x18,0x3d,0xe5,0x9a,0x57,0x02,0xa1,0x92,0xf3,0x59,0x31,0x71,0x68,0xf5,0x35,0xef,0x1e,0xba,0xec,0x55,0x84,0x8f,0x39,0x8c,0x45,0x72,0xa8,0xc9,0x1e,0x9b,0x50,0xa2,0x00,0xd4,0xa4,0xe6,0xb8,0xb4,0x82,0xc8,0x0b,0x02,0xd7,0x81,0x9b,0x61,0x75,0x95,0xf1,0x9b,0xcc,0xe7,0x57,0x60,0x64,0xcd,0xc7,0xa5,0x88,0xdd,0x3a},
+    {0xf2,0xdc,0x35,0xb6,0x70,0x57,0x89,0xab,0xbc,0x1f,0x6c,0xf6,0x6c,0xef,0xdf,0x02,0x87,0xd1,0xb6,0xbe,0x68,0x02,0x53,0x85,0x74,0x9e,0x87,0xcc,0xfc,0x29,0x99,0x24,0x46,0x30,0x39,0x59,0xd4,0x98,0xc2,0x85,0xec,0x59,0xf6,0x5f,0x98,0x35,0x7e,0x8f,0x3a,0x6e,0xf6,0xf2,0x2a,0xa2,0x2c,0x1d,0x20,0xa7,0x06,0xa4,0x31,0x11,0xba,0x61,0x29,0x90,0x95,0x16,0xf1,0xa0,0xd0,0xa3,0x89,0xbd,0x7e,0xba,0x6c,0x6b,0x3b,0x02,0x07,0x33,0x78,0x26,0x3e,0x5a,0xf1,0x7b,0xe7,0xec,0xd8,0xbb,0x0c,0x31,0x20,0x56},
+    {0x43,0xd6,0x34,0x49,0x43,0x93,0x89,0x52,0xf5,0x22,0x12,0xa5,0x06,0xf8,0xdb,0xb9,0x22,0x1c,0xf4,0xc3,0x8f,0x87,0x6d,0x8f,0x30,0x97,0x9d,0x4d,0x2a,0x6a,0x67,0x37,0xd6,0x85,0xe2,0x77,0xf4,0xb5,0x46,0x66,0x93,0x61,0x8f,0x6c,0x67,0xff,0xe8,0x40,0xdd,0x94,0xb5,0xab,0x11,0x73,0xec,0xa6,0x4d,0xec,0x8c,0x65,0xf3,0x46,0xc8,0x7e,0xc7,0x2e,0xa2,0x1d,0x3f,0x8f,0x5e,0x9b,0x13,0xcd,0x01,0x6c,0x77,0x1d,0x0f,0x13,0xb8,0x9f,0x98,0xa2,0xcf,0x8f,0x4c,0x21,0xd5,0x9d,0x9b,0x39,0x23,0xf7,0xaa,0x6d},
+    {0x47,0xbe,0x3d,0xeb,0x62,0x75,0x3a,0x5f,0xb8,0xa0,0xbd,0x8e,0x54,0x38,0xea,0xf7,0x99,0x72,0x74,0x45,0x31,0xe5,0xc3,0x00,0x51,0xd5,0x27,0x16,0xe7,0xe9,0x04,0x13,0xa2,0x8e,0xad,0xac,0xbf,0x04,0x3b,0x58,0x84,0xe8,0x8b,0x14,0xe8,0x43,0xb7,0x29,0xdb,0xc5,0x10,0x08,0x3b,0x58,0x1e,0x2b,0xaa,0xbb,0xb3,0x8e,0xe5,0x49,0x54,0x2b,0xfe,0x9c,0xdc,0x6a,0xd2,0x14,0x98,0x78,0x0b,0xdd,0x48,0x8b,0x3f,0xab,0x1b,0x3c,0x0a,0xc6,0x79,0xf9,0xff,0xe1,0x0f,0xda,0x93,0xd6,0x2d,0x7c,0x2d,0xde,0x68,0x44},
+    {0x9e,0x46,0x19,0x94,0x5e,0x35,0xbb,0x51,0x54,0xc7,0xdd,0x23,0x4c,0xdc,0xe6,0x33,0x62,0x99,0x7f,0x44,0xd6,0xb6,0xa5,0x93,0x63,0xbd,0x44,0xfb,0x6f,0x7c,0xce,0x6c,0xce,0x07,0x63,0xf8,0xc6,0xd8,0x9a,0x4b,0x28,0x0c,0x5d,0x43,0x31,0x35,0x11,0x21,0x2c,0x77,0x7a,0x65,0xc5,0x66,0xa8,0xd4,0x52,0x73,0x24,0x63,0x7e,0x42,0xa6,0x5d,0xca,0x22,0xac,0xde,0x88,0xc6,0x94,0x1a,0xf8,0x1f,0xae,0xbb,0xf7,0x6e,0x06,0xb9,0x0f,0x58,0x59,0x8d,0x38,0x8c,0xad,0x88,0xa8,0x2c,0x9f,0xe7,0xbf,0x9a,0xf2,0x58},
+    {0x68,0x3e,0xe7,0x8d,0xab,0xcf,0x0e,0xe9,0xa5,0x76,0x7e,0x37,0x9f,0x6f,0x03,0x54,0x82,0x59,0x01,0xbe,0x0b,0x5b,0x49,0xf0,0x36,0x1e,0xf4,0xa7,0xc4,0x29,0x76,0x57,0xf6,0xcd,0x0e,0x71,0xbf,0x64,0x5a,0x4b,0x3c,0x29,0x2c,0x46,0x38,0xe5,0x4c,0xb1,0xb9,0x3a,0x0b,0xd5,0x56,0xd0,0x43,0x36,0x70,0x48,0x5b,0x18,0x24,0x37,0xf9,0x6a,0x88,0xa8,0xc6,0x09,0x45,0x02,0x20,0x32,0x73,0x89,0x55,0x4b,0x13,0x36,0xe0,0xd2,0x9f,0x28,0x33,0x3c,0x23,0x36,0xe2,0x83,0x8f,0xc1,0xae,0x0c,0xbb,0x25,0x1f,0x70},
+    {0xed,0x6c,0x61,0xe4,0xf8,0xb0,0xa8,0xc3,0x7d,0xa8,0x25,0x9e,0x0e,0x66,0x00,0xf7,0x9c,0xa5,0xbc,0xf4,0x1f,0x06,0xe3,0x61,0xe9,0x0b,0xc4,0xbd,0xbf,0x92,0x0c,0x2e,0x13,0xc1,0xbe,0x7c,0xd9,0xf6,0x18,0x9d,0xe4,0xdb,0xbf,0x74,0xe6,0x06,0x4a,0x84,0xd6,0x60,0x4e,0xac,0x22,0xb5,0xf5,0x20,0x51,0x5e,0x95,0x50,0xc0,0x5b,0x0a,0x72,0x35,0x5a,0x80,0x9b,0x43,0x09,0x3f,0x0c,0xfc,0xab,0x42,0x62,0x37,0x8b,0x4e,0xe8,0x46,0x93,0x22,0x5c,0xf3,0x17,0x14,0x69,0xec,0xf0,0x4e,0x14,0xbb,0x9c,0x9b,0x0e},
+    {0xad,0x20,0x57,0xfb,0x8f,0xd4,0xba,0xfb,0x0e,0x0d,0xf9,0xdb,0x6b,0x91,0x81,0xee,0xbf,0x43,0x55,0x63,0x52,0x31,0x81,0xd4,0xd8,0x7b,0x33,0x3f,0xeb,0x04,0x11,0x22,0xee,0xbe,0xb1,0x5d,0xd5,0x9b,0xee,0x8d,0xb9,0x3f,0x72,0x0a,0x37,0xab,0xc3,0xc9,0x91,0xd7,0x68,0x1c,0xbf,0xf1,0xa8,0x44,0xde,0x3c,0xfd,0x1c,0x19,0x44,0x6d,0x36,0x14,0x8c,0xbc,0xf2,0x43,0x17,0x3c,0x9e,0x3b,0x6c,0x85,0xb5,0xfc,0x26,0xda,0x2e,0x97,0xfb,0xa7,0x68,0x0e,0x2f,0xb8,0xcc,0x44,0x32,0x59,0xbc,0xe6,0xa4,0x67,0x41},
+    {0x00,0x27,0xf6,0x76,0x28,0x9d,0x3b,0x64,0xeb,0x68,0x76,0x0e,0x40,0x9d,0x1d,0x5d,0x84,0x06,0xfc,0x21,0x03,0x43,0x4b,0x1b,0x6a,0x24,0x55,0x22,0x7e,0xbb,0x38,0x79,0xee,0x8f,0xce,0xf8,0x65,0x26,0xbe,0xc2,0x2c,0xd6,0x80,0xe8,0x14,0xff,0x67,0xe9,0xee,0x4e,0x36,0x2f,0x7e,0x6e,0x2e,0xf1,0xf6,0xd2,0x7e,0xcb,0x70,0x33,0xb3,0x34,0xcc,0xd6,0x81,0x86,0xee,0x91,0xc5,0xcd,0x53,0xa7,0x85,0xed,0x9c,0x10,0x02,0xce,0x83,0x88,0x80,0x58,0xc1,0x85,0x74,0xed,0xe4,0x65,0xfe,0x2d,0x6e,0xfc,0x76,0x11},
+    {0x9b,0x61,0x9c,0x5b,0xd0,0x6c,0xaf,0xb4,0x80,0x84,0xa5,0xb2,0xf4,0xc9,0xdf,0x2d,0xc4,0x4d,0xe9,0xeb,0x02,0xa5,0x4f,0x3d,0x34,0x5f,0x7d,0x67,0x4c,0x3a,0xfc,0x08,0xb8,0x0e,0x77,0x49,0x89,0xe2,0x90,0xdb,0xa3,0x40,0xf4,0xac,0x2a,0xcc,0xfb,0x98,0x9b,0x87,0xd7,0xde,0xfe,0x4f,0x35,0x21,0xb6,0x06,0x69,0xf2,0x54,0x3e,0x6a,0x1f,0xea,0x34,0x07,0xd3,0x99,0xc1,0xa4,0x60,0xd6,0x5c,0x16,0x31,0xb6,0x85,0xc0,0x40,0x95,0x82,0x59,0xf7,0x23,0x3e,0x33,0xe2,0xd1,0x00,0xb9,0x16,0x01,0xad,0x2f,0x4f},
+    {0x54,0x4e,0xae,0x94,0x41,0xb2,0xbe,0x44,0x6c,0xef,0x57,0x18,0x51,0x1c,0x54,0x5f,0x98,0x04,0x8d,0x36,0x2d,0x6b,0x1e,0xa6,0xab,0xf7,0x2e,0x97,0xa4,0x84,0x54,0x44,0x38,0xb6,0x3b,0xb7,0x1d,0xd9,0x2c,0x96,0x08,0x9c,0x12,0xfc,0xaa,0x77,0x05,0xe6,0x89,0x16,0xb6,0xf3,0x39,0x9b,0x61,0x6f,0x81,0xee,0x44,0x29,0x5f,0x99,0x51,0x34,0x7c,0x7d,0xea,0x9f,0xd0,0xfc,0x52,0x91,0xf6,0x5c,0x93,0xb0,0x94,0x6c,0x81,0x4a,0x40,0x5c,0x28,0x47,0xaa,0x9a,0x8e,0x25,0xb7,0x93,0x28,0x04,0xa6,0x9c,0xb8,0x10},
+    {0x9c,0x28,0x18,0x97,0x49,0x47,0x59,0x3d,0x26,0x3f,0x53,0x24,0xc5,0xf8,0xeb,0x12,0x15,0xef,0xc3,0x14,0xcb,0xbf,0x62,0x02,0x8e,0x51,0xb7,0x77,0xd5,0x78,0xb8,0x20,0x6e,0xf0,0x45,0x5a,0xbe,0x41,0x39,0x75,0x65,0x5f,0x9c,0x6d,0xed,0xae,0x7c,0xd0,0xb6,0x51,0xff,0x72,0x9c,0x6b,0x77,0x11,0xa9,0x4d,0x0d,0xef,0xd9,0xd1,0xd2,0x17,0x6a,0x3e,0x3f,0x07,0x18,0xaf,0xf2,0x27,0x69,0x10,0x52,0xd7,0x19,0xe5,0x3f,0xfd,0x22,0x00,0xa6,0x3c,0x2c,0xb7,0xe3,0x22,0xa7,0xc6,0x65,0xcc,0x63,0x4f,0x21,0x72},
+    {0x93,0xa6,0x07,0x53,0x40,0x7f,0xe3,0xb4,0x95,0x67,0x33,0x2f,0xd7,0x14,0xa7,0xab,0x99,0x10,0x76,0x73,0xa7,0xd0,0xfb,0xd6,0xc9,0xcb,0x71,0x81,0xc5,0x48,0xdf,0x5f,0xc9,0x29,0x3b,0xf4,0xb9,0xb7,0x9d,0x1d,0x75,0x8f,0x51,0x4f,0x4a,0x82,0x05,0xd6,0xc4,0x9d,0x2f,0x31,0xbd,0x72,0xc0,0xf2,0xb0,0x45,0x15,0x5a,0x85,0xac,0x24,0x1f,0xaa,0x05,0x95,0x8e,0x32,0x08,0xd6,0x24,0xee,0x20,0x14,0x0c,0xd1,0xc1,0x48,0x47,0xa2,0x25,0xfb,0x06,0x5c,0xe4,0xff,0xc7,0xe6,0x95,0xe3,0x2a,0x9e,0x73,0xba,0x00},
+    {0xd6,0x90,0x87,0x5c,0xde,0x98,0x2e,0x59,0xdf,0xa2,0xc2,0x45,0xd3,0xb7,0xbf,0xe5,0x22,0x99,0xb4,0xf9,0x60,0x3b,0x5a,0x11,0xf3,0x78,0xad,0x67,0x3e,0x3a,0x28,0x03,0x26,0xbb,0x88,0xea,0xf5,0x26,0x44,0xae,0xfb,0x3b,0x97,0x84,0xd9,0x79,0x06,0x36,0x50,0x4e,0x69,0x26,0x0c,0x03,0x9f,0x5c,0x26,0xd2,0x18,0xd5,0xe7,0x7d,0x29,0x72,0x39,0xb9,0x0c,0xbe,0xc7,0x1d,0x24,0x48,0x80,0x30,0x63,0x8b,0x4d,0x9b,0xf1,0x32,0x08,0x93,0x28,0x02,0x0d,0xc9,0xdf,0xd3,0x45,0x19,0x27,0x46,0x68,0x29,0xe1,0x05},
+    {0x5a,0x49,0x9c,0x2d,0xb3,0xee,0x82,0xba,0x7c,0xb9,0x2b,0xf1,0xfc,0xc8,0xef,0xce,0xe0,0xd1,0xb5,0x93,0xae,0xab,0x2d,0xb0,0x9b,0x8d,0x69,0x13,0x9c,0x0c,0xc0,0x39,0x50,0x45,0x2c,0x24,0xc8,0xbb,0xbf,0xad,0xd9,0x81,0x30,0xd0,0xec,0x0c,0xc8,0xbc,0x92,0xdf,0xc8,0xf5,0xa6,0x66,0x35,0x84,0x4c,0xce,0x58,0x82,0xd3,0x25,0xcf,0x78,0x68,0x9d,0x48,0x31,0x8e,0x6b,0xae,0x15,0x87,0xf0,0x2b,0x9c,0xab,0x1c,0x85,0xaa,0x05,0xfa,0x4e,0xf0,0x97,0x5a,0xa7,0xc9,0x32,0xf8,0x3f,0x6b,0x07,0x52,0x6b,0x00},
+    {0x1c,0x78,0x95,0x9d,0xe1,0xcf,0xe0,0x29,0xe2,0x10,0x63,0x96,0x18,0xdf,0x81,0xb6,0x39,0x6b,0x51,0x70,0xd3,0x39,0xdf,0x57,0x22,0x61,0xc7,0x3b,0x44,0xe3,0x57,0x4d,0x2d,0x08,0xce,0xb9,0x16,0x7e,0xcb,0xf5,0x29,0xbc,0x7a,0x41,0x4c,0xf1,0x07,0x34,0xab,0xa7,0xf4,0x2b,0xce,0x6b,0xb3,0xd4,0xce,0x75,0x9f,0x1a,0x56,0xe9,0xe2,0x7d,0xcb,0x5e,0xa5,0xb6,0xf4,0xd4,0x70,0xde,0x99,0xdb,0x85,0x5d,0x7f,0x52,0x01,0x48,0x81,0x9a,0xee,0xd3,0x40,0xc4,0xc9,0xdb,0xed,0x29,0x60,0x1a,0xaf,0x90,0x2a,0x6b},
+    {0x97,0x1e,0xe6,0x9a,0xfc,0xf4,0x23,0x69,0xd1,0x5f,0x3f,0xe0,0x1d,0x28,0x35,0x57,0x2d,0xd1,0xed,0xe6,0x43,0xae,0x64,0xa7,0x4a,0x3e,0x2d,0xd1,0xe9,0xf4,0xd8,0x5f,0x0a,0xd8,0xb2,0x5b,0x24,0xf3,0xeb,0x77,0x9b,0x07,0xb9,0x2f,0x47,0x1b,0x30,0xd8,0x33,0x73,0xee,0x4c,0xf2,0xe6,0x47,0xc6,0x09,0x21,0x6c,0x27,0xc8,0x12,0x58,0x46,0xd9,0x62,0x10,0x2a,0xb2,0xbe,0x43,0x4d,0x16,0xdc,0x31,0x38,0x75,0xfb,0x65,0x70,0xd7,0x68,0x29,0xde,0x7b,0x4a,0x0d,0x18,0x90,0x67,0xb1,0x1c,0x2b,0x2c,0xb3,0x05},
+    {0xfd,0xa8,0x4d,0xd2,0xcc,0x5e,0xc0,0xc8,0x83,0xef,0xdf,0x05,0xac,0x1a,0xcf,0xa1,0x61,0xcd,0xf9,0x7d,0xf2,0xef,0xbe,0xdb,0x99,0x1e,0x47,0x7b,0xa3,0x56,0x55,0x3b,0x95,0x81,0xd5,0x7a,0x2c,0xa4,0xfc,0xf7,0xcc,0xf3,0x33,0x43,0x6e,0x28,0x14,0x32,0x9d,0x97,0x0b,0x34,0x0d,0x9d,0xc2,0xb6,0xe1,0x07,0x73,0x56,0x48,0x1a,0x77,0x31,0x82,0xd4,0x4d,0xe1,0x24,0xc5,0xb0,0x32,0xb6,0xa4,0x2b,0x1a,0x54,0x51,0xb3,0xed,0xf3,0x5a,0x2b,0x28,0x48,0x60,0xd1,0xa3,0xeb,0x36,0x73,0x7a,0xd2,0x79,0xc0,0x4f},
+    {0x7f,0x2f,0xbf,0x89,0xb0,0x38,0xc9,0x51,0xa7,0xe9,0xdf,0x02,0x65,0xbd,0x97,0x24,0x53,0xe4,0x80,0x78,0x9c,0xc0,0xff,0xff,0x92,0x8e,0xf9,0xca,0xce,0x67,0x45,0x12,0x0d,0xc5,0x86,0x0c,0x44,0x8b,0x34,0xdc,0x51,0xe6,0x94,0xcc,0xc9,0xcb,0x37,0x13,0xb9,0x3c,0x3e,0x64,0x4d,0xf7,0x22,0x64,0x08,0xcd,0xe3,0xba,0xc2,0x70,0x11,0x24,0xb4,0x73,0xc4,0x0a,0x86,0xab,0xf9,0x3f,0x35,0xe4,0x13,0x01,0xee,0x1d,0x91,0xf0,0xaf,0xc4,0xc6,0xeb,0x60,0x50,0xe7,0x4a,0x0d,0x00,0x87,0x6c,0x96,0x12,0x86,0x3f},
+    {0xde,0x0d,0x2a,0x78,0xc9,0x0c,0x9a,0x55,0x85,0x83,0x71,0xea,0xb2,0xcd,0x1d,0x55,0x8c,0x23,0xef,0x31,0x5b,0x86,0x62,0x7f,0x3d,0x61,0x73,0x79,0x76,0xa7,0x4a,0x50,0x13,0x8d,0x04,0x36,0xfa,0xfc,0x18,0x9c,0xdd,0x9d,0x89,0x73,0xb3,0x9d,0x15,0x29,0xaa,0xd0,0x92,0x9f,0x0b,0x35,0x9f,0xdc,0xd4,0x19,0x8a,0x87,0xee,0x7e,0xf5,0x26,0xb1,0xef,0x87,0x56,0xd5,0x2c,0xab,0x0c,0x7b,0xf1,0x7a,0x24,0x62,0xd1,0x80,0x51,0x67,0x24,0x5a,0x4f,0x34,0x5a,0xc1,0x85,0x69,0x30,0xba,0x9d,0x3d,0x94,0x41,0x40},
+    {0x96,0xcc,0xeb,0x43,0xba,0xee,0xc0,0xc3,0xaf,0x9c,0xea,0x26,0x9c,0x9c,0x74,0x8d,0xc6,0xcc,0x77,0x1c,0xee,0x95,0xfa,0xd9,0x0f,0x34,0x84,0x76,0xd9,0xa1,0x20,0x14,0xdd,0xaa,0x6c,0xa2,0x43,0x77,0x21,0x4b,0xce,0xb7,0x8a,0x64,0x24,0xb4,0xa6,0x47,0xe3,0xc9,0xfb,0x03,0x7a,0x4f,0x1d,0xcb,0x19,0xd0,0x00,0x98,0x42,0x31,0xd9,0x12,0x4f,0x59,0x37,0xd3,0x99,0x77,0xc6,0x00,0x7b,0xa4,0x3a,0xb2,0x40,0x51,0x3c,0x5e,0x95,0xf3,0x5f,0xe3,0x54,0x28,0x18,0x44,0x12,0xa0,0x59,0x43,0x31,0x92,0x4f,0x1b},
+    {0x51,0x09,0x15,0x89,0x9d,0x10,0x5c,0x3e,0x6a,0x69,0xe9,0x2d,0x91,0xfa,0xce,0x39,0x20,0x30,0x5f,0x97,0x3f,0xe4,0xea,0x20,0xae,0x2d,0x13,0x7f,0x2a,0x57,0x9b,0x23,0xb1,0x66,0x98,0xa4,0x30,0x30,0xcf,0x33,0x59,0x48,0x5f,0x21,0xd2,0x73,0x1f,0x25,0xf6,0xf4,0xde,0x51,0x40,0xaa,0x82,0xab,0xf6,0x23,0x9a,0x6f,0xd5,0x91,0xf1,0x5f,0x68,0x90,0x2d,0xac,0x33,0xd4,0x9e,0x81,0x23,0x85,0xc9,0x5f,0x79,0xab,0x83,0x28,0x3d,0xeb,0x93,0x55,0x80,0x72,0x45,0xef,0xcb,0x36,0x8f,0x75,0x6a,0x52,0x0c,0x02},
+    {0xbc,0xdb,0xd8,0x9e,0xf8,0x34,0x98,0x77,0x6c,0xa4,0x7c,0xdc,0xf9,0xaa,0xf2,0xc8,0x74,0xb0,0xe1,0xa3,0xdc,0x4c,0x52,0xa9,0x77,0x38,0x31,0x15,0x46,0xcc,0xaa,0x02,0x89,0xcc,0x42,0xf0,0x59,0xef,0x31,0xe9,0xb6,0x4b,0x12,0x8e,0x9d,0x9c,0x58,0x2c,0x97,0x59,0xc7,0xae,0x8a,0xe1,0xc8,0xad,0x0c,0xc5,0x02,0x56,0x0a,0xfe,0x2c,0x45,0xdf,0x77,0x78,0x64,0xa0,0xf7,0xa0,0x86,0x9f,0x7c,0x60,0x0e,0x27,0x64,0xc4,0xbb,0xc9,0x11,0xfb,0xf1,0x25,0xea,0x17,0xab,0x7b,0x87,0x4b,0x30,0x7b,0x7d,0xfb,0x4c},
+    {0xfe,0x75,0x9b,0xb8,0x6c,0x3d,0xb4,0x72,0x80,0xdc,0x6a,0x9c,0xd9,0x94,0xc6,0x54,0x9f,0x4c,0xe3,0x3e,0x37,0xaa,0xc3,0xb8,0x64,0x53,0x07,0x39,0x2b,0x62,0xb4,0x14,0x12,0xef,0x89,0x97,0xc2,0x99,0x86,0xe2,0x0d,0x19,0x57,0xdf,0x71,0xcd,0x6e,0x2b,0xd0,0x70,0xc9,0xec,0x57,0xc8,0x43,0xc3,0xc5,0x3a,0x4d,0x43,0xbc,0x4c,0x1d,0x5b,0x26,0x9f,0x0a,0xcc,0x15,0x26,0xfb,0xb6,0xe5,0xcc,0x8d,0xb8,0x2b,0x0e,0x4f,0x3a,0x05,0xa7,0x69,0x33,0x8b,0x49,0x01,0x13,0xd1,0x2d,0x59,0x58,0x12,0xf7,0x98,0x2f},
+    {0x56,0x9e,0x0f,0xb5,0x4c,0xa7,0x94,0x0c,0x20,0x13,0x8e,0x8e,0xa9,0xf4,0x1f,0x5b,0x67,0x0f,0x30,0x82,0x21,0xcc,0x2a,0x9a,0xf9,0xaa,0x06,0xd8,0x49,0xe2,0x6a,0x3a,0x01,0xa7,0x54,0x4f,0x44,0xae,0x12,0x2e,0xde,0xd7,0xcb,0xa9,0xf0,0x3e,0xfe,0xfc,0xe0,0x5d,0x83,0x75,0x0d,0x89,0xbf,0xce,0x54,0x45,0x61,0xe7,0xe9,0x62,0x80,0x1d,0x5a,0x7c,0x90,0xa9,0x85,0xda,0x7a,0x65,0x62,0x0f,0xb9,0x91,0xb5,0xa8,0x0e,0x1a,0xe9,0xb4,0x34,0xdf,0xfb,0x1d,0x0e,0x8d,0xf3,0x5f,0xf2,0xae,0xe8,0x8c,0x8b,0x29},
+    {0xb2,0x0c,0xf7,0xef,0x53,0x79,0x92,0x2a,0x76,0x70,0x15,0x79,0x2a,0xc9,0x89,0x4b,0x6a,0xcf,0xa7,0x30,0x7a,0x45,0x18,0x94,0x85,0xe4,0x5c,0x4d,0x40,0xa8,0xb8,0x34,0xde,0x65,0x21,0x0a,0xea,0x72,0x7a,0x83,0xf6,0x79,0xcf,0x0b,0xb4,0x07,0xab,0x3f,0x70,0xae,0x38,0x77,0xc7,0x36,0x16,0x52,0xdc,0xd7,0xa7,0x03,0x18,0x27,0xa6,0x6b,0x35,0x33,0x69,0x83,0xb5,0xec,0x6e,0xc2,0xfd,0xfe,0xb5,0x63,0xdf,0x13,0xa8,0xd5,0x73,0x25,0xb2,0xa4,0x9a,0xaa,0x93,0xa2,0x6a,0x1c,0x5e,0x46,0xdd,0x2b,0xd6,0x71},
+    {0x80,0xdf,0x78,0xd3,0x28,0xcc,0x33,0x65,0xb4,0xa4,0x0f,0x0a,0x79,0x43,0xdb,0xf6,0x5a,0xda,0x01,0xf7,0xf9,0x5f,0x64,0xe3,0xa4,0x2b,0x17,0xf3,0x17,0xf3,0xd5,0x74,0xf5,0x5e,0xf7,0xb1,0xda,0xb5,0x2d,0xcd,0xf5,0x65,0xb0,0x16,0xcf,0x95,0x7f,0xd7,0x85,0xf0,0x49,0x3f,0xea,0x1f,0x57,0x14,0x3d,0x2b,0x2b,0x26,0x21,0x36,0x33,0x1c,0x81,0xca,0xd9,0x67,0x54,0xe5,0x6f,0xa8,0x37,0x8c,0x29,0x2b,0x75,0x7c,0x8b,0x39,0x3b,0x62,0xac,0xe3,0x92,0x08,0x6d,0xda,0x8c,0xd9,0xe9,0x47,0x45,0xcc,0xeb,0x4a},
+    {0xc9,0x01,0x6d,0x27,0x1b,0x07,0xf0,0x12,0x70,0x8c,0xc4,0x86,0xc5,0xba,0xb8,0xe7,0xa9,0xfb,0xd6,0x71,0x9b,0x12,0x08,0x53,0x92,0xb7,0x3d,0x5a,0xf9,0xfb,0x88,0x5d,0x10,0xb6,0x54,0x73,0x9e,0x8d,0x40,0x0b,0x6e,0x5b,0xa8,0x5b,0x53,0x32,0x6b,0x80,0x07,0xa2,0x58,0x4a,0x03,0x3a,0xe6,0xdb,0x2c,0xdf,0xa1,0xc9,0xdd,0xd9,0x3b,0x17,0xdf,0x72,0x58,0xfe,0x1e,0x0f,0x50,0x2b,0xc1,0x18,0x39,0xd4,0x2e,0x58,0xd6,0x58,0xe0,0x3a,0x67,0xc9,0x8e,0x27,0xed,0xe6,0x19,0xa3,0x9e,0xb1,0x13,0xcd,0xe1,0x06},
+    {0x23,0x6f,0x16,0x6f,0x51,0xad,0xd0,0x40,0xbe,0x6a,0xab,0x1f,0x93,0x32,0x8e,0x11,0x8e,0x08,0x4d,0xa0,0x14,0x5e,0xe3,0x3f,0x66,0x62,0xe1,0x26,0x35,0x60,0x80,0x30,0x53,0x03,0x5b,0x9e,0x62,0xaf,0x2b,0x47,0x47,0x04,0x8d,0x27,0x90,0x0b,0xaa,0x3b,0x27,0xbf,0x43,0x96,0x46,0x5f,0x78,0x0c,0x13,0x7b,0x83,0x8d,0x1a,0x6a,0x3a,0x7f,0x0b,0x80,0x3d,0x5d,0x39,0x44,0xe6,0xf7,0xf6,0xed,0x01,0xc9,0x55,0xd5,0xa8,0x95,0x39,0x63,0x2c,0x59,0x30,0x78,0xcd,0x68,0x7e,0x30,0x51,0x2e,0xed,0xfd,0xd0,0x30},
+    {0xb3,0x33,0x12,0xf2,0x1a,0x4d,0x59,0xe0,0x9c,0x4d,0xcc,0xf0,0x8e,0xe7,0xdb,0x1b,0x77,0x9a,0x49,0x8f,0x7f,0x18,0x65,0x69,0x68,0x98,0x09,0x2c,0x20,0x14,0x92,0x0a,0x50,0x47,0xb8,0x68,0x1e,0x97,0xb4,0x9c,0xcf,0xbb,0x64,0x66,0x29,0x72,0x95,0xa0,0x2b,0x41,0xfa,0x72,0x26,0xe7,0x8d,0x5c,0xd9,0x89,0xc5,0x51,0x43,0x08,0x15,0x46,0x2e,0xa0,0xb9,0xae,0xc0,0x19,0x90,0xbc,0xae,0x4c,0x03,0x16,0x0d,0x11,0xc7,0x55,0xec,0x32,0x99,0x65,0x01,0xf5,0x6d,0x0e,0xfe,0x5d,0xca,0x95,0x28,0x0d,0xca,0x3b},
+    {0xa4,0x62,0x5d,0x3c,0xbc,0x31,0xf0,0x40,0x60,0x7a,0xf0,0xcf,0x3e,0x8b,0xfc,0x19,0x45,0xb5,0x0f,0x13,0xa2,0x3d,0x18,0x98,0xcd,0x13,0x8f,0xae,0xdd,0xde,0x31,0x56,0xbf,0x01,0xcc,0x9e,0xb6,0x8e,0x68,0x9c,0x6f,0x89,0x44,0xa6,0xad,0x83,0xbc,0xf0,0xe2,0x9f,0x7a,0x5f,0x5f,0x95,0x2d,0xca,0x41,0x82,0xf2,0x8d,0x03,0xb4,0xa8,0x4e,0x02,0xd2,0xca,0xf1,0x0a,0x46,0xed,0x2a,0x83,0xee,0x8c,0xa4,0x05,0x53,0x30,0x46,0x5f,0x1a,0xf1,0x49,0x45,0x77,0x21,0x91,0x63,0xa4,0x2c,0x54,0x30,0x09,0xce,0x24},
+    {0x06,0xc1,0x06,0xfd,0xf5,0x90,0xe8,0x1f,0xf2,0x10,0x88,0x5d,0x35,0x68,0xc4,0xb5,0x3e,0xaf,0x8c,0x6e,0xfe,0x08,0x78,0x82,0x4b,0xd7,0x06,0x8a,0xc2,0xe3,0xd4,0x41,0x85,0x0b,0xf3,0xfd,0x55,0xa1,0xcf,0x3f,0xa4,0x2e,0x37,0x36,0x8e,0x16,0xf7,0xd2,0x44,0xf8,0x92,0x64,0xde,0x64,0xe0,0xb2,0x80,0x42,0x4f,0x32,0xa7,0x28,0x99,0x54,0x2e,0x1a,0xee,0x63,0xa7,0x32,0x6e,0xf2,0xea,0xfd,0x5f,0xd2,0xb7,0xe4,0x91,0xae,0x69,0x4d,0x7f,0xd1,0x3b,0xd3,0x3b,0xbc,0x6a,0xff,0xdc,0xc0,0xde,0x66,0x1b,0x49},
+    {0xa7,0x32,0xea,0xc7,0x3d,0xb1,0xf5,0x98,0x98,0xdb,0x16,0x7e,0xcc,0xf8,0xd5,0xe3,0x47,0xd9,0xf8,0xcb,0x52,0xbf,0x0a,0xac,0xac,0xe4,0x5e,0xc8,0xd0,0x38,0xf3,0x08,0xa1,0x64,0xda,0xd0,0x8e,0x4a,0xf0,0x75,0x4b,0x28,0xe2,0x67,0xaf,0x2c,0x22,0xed,0xa4,0x7b,0x7b,0x1f,0x79,0xa3,0x34,0x82,0x67,0x8b,0x01,0xb7,0xb0,0xb8,0xf6,0x4c,0xbd,0x73,0x1a,0x99,0x21,0xa8,0x83,0xc3,0x7a,0x0c,0x32,0xdf,0x01,0xbc,0x27,0xab,0x63,0x70,0x77,0x84,0x1b,0x33,0x3d,0xc1,0x99,0x8a,0x07,0xeb,0x82,0x4a,0x0d,0x53},
+    {0x25,0x48,0xf9,0xe1,0x30,0x36,0x4c,0x00,0x5a,0x53,0xab,0x8c,0x26,0x78,0x2d,0x7e,0x8b,0xff,0x84,0xcc,0x23,0x23,0x48,0xc7,0xb9,0x70,0x17,0x10,0x3f,0x75,0xea,0x65,0x9e,0xbf,0x9a,0x6c,0x45,0x73,0x69,0x6d,0x80,0xa8,0x00,0x49,0xfc,0xb2,0x7f,0x25,0x50,0xb8,0xcf,0xc8,0x12,0xf4,0xac,0x2b,0x5b,0xbd,0xbf,0x0c,0xe0,0xe7,0xb3,0x0d,0x63,0x63,0x09,0xe2,0x3e,0xfc,0x66,0x3d,0x6b,0xcb,0xb5,0x61,0x7f,0x2c,0xd6,0x81,0x1a,0x3b,0x44,0x13,0x42,0x04,0xbe,0x0f,0xdb,0xa1,0xe1,0x21,0x19,0xec,0xa4,0x02},
+    {0xa2,0xb8,0x24,0x3b,0x9a,0x25,0xe6,0x5c,0xb8,0xa0,0xaf,0x45,0xcc,0x7a,0x57,0xb8,0x37,0x70,0xa0,0x8b,0xe8,0xe6,0xcb,0xcc,0xbf,0x09,0x78,0x12,0x51,0x3c,0x14,0x3d,0x5f,0x79,0xcf,0xf1,0x62,0x61,0xc8,0xf5,0xf2,0x57,0xee,0x26,0x19,0x86,0x8c,0x11,0x78,0x35,0x06,0x1c,0x85,0x24,0x21,0x17,0xcf,0x7f,0x06,0xec,0x5d,0x2b,0xd1,0x36,0x57,0x45,0x15,0x79,0x91,0x27,0x6d,0x12,0x0a,0x3a,0x78,0xfc,0x5c,0x8f,0xe4,0xd5,0xac,0x9b,0x17,0xdf,0xe8,0xb6,0xbd,0x36,0x59,0x28,0xa8,0x5b,0x88,0x17,0xf5,0x2e},
+    {0xdc,0xae,0x58,0x8c,0x4e,0x97,0x37,0x46,0xa4,0x41,0xf0,0xab,0xfb,0x22,0xef,0xb9,0x8a,0x71,0x80,0xe9,0x56,0xd9,0x85,0xe1,0xa6,0xa8,0x43,0xb1,0xfa,0x78,0x1b,0x2f,0x51,0x2f,0x5b,0x30,0xfb,0xbf,0xee,0x96,0xb8,0x96,0x95,0x88,0xad,0x38,0xf9,0xd3,0x25,0xdd,0xd5,0x46,0xc7,0x2d,0xf5,0xf0,0x95,0x00,0x3a,0xbb,0x90,0x82,0x96,0x57,0x01,0xe1,0x20,0x0a,0x43,0xb8,0x1a,0xf7,0x47,0xec,0xf0,0x24,0x8d,0x65,0x93,0xf3,0xd1,0xee,0xe2,0x6e,0xa8,0x09,0x75,0xcf,0xe1,0xa3,0x2a,0xdc,0x35,0x3e,0xc4,0x7d},
+    {0xc3,0xd9,0x7d,0x88,0x65,0x66,0x96,0x85,0x55,0x53,0xb0,0x4b,0x31,0x9b,0x0f,0xc9,0xb1,0x79,0x20,0xef,0xf8,0x8d,0xe0,0xc6,0x2f,0xc1,0x8c,0x75,0x16,0x20,0xf7,0x7e,0x18,0x97,0x3e,0x27,0x5c,0x2a,0x78,0x5a,0x94,0xfd,0x4e,0x5e,0x99,0xc6,0x76,0x35,0x3e,0x7d,0x23,0x1f,0x05,0xd8,0x2e,0x0f,0x99,0x0a,0xd5,0x82,0x1d,0xb8,0x4f,0x04,0xd9,0xe3,0x07,0xa9,0xc5,0x18,0xdf,0xc1,0x59,0x63,0x4c,0xce,0x1d,0x37,0xb3,0x57,0x49,0xbb,0x01,0xb2,0x34,0x45,0x70,0xca,0x2e,0xdd,0x30,0x9c,0x3f,0x82,0x79,0x7f},
+    {0xe8,0x13,0xb5,0xa3,0x39,0xd2,0x34,0x83,0xd8,0xa8,0x1f,0xb9,0xd4,0x70,0x36,0xc1,0x33,0xbd,0x90,0xf5,0x36,0x41,0xb5,0x12,0xb4,0xd9,0x84,0xd7,0x73,0x03,0x4e,0x0a,0xba,0x87,0xf5,0x68,0xf0,0x1f,0x9c,0x6a,0xde,0xc8,0x50,0x00,0x4e,0x89,0x27,0x08,0xe7,0x5b,0xed,0x7d,0x55,0x99,0xbf,0x3c,0xf0,0xd6,0x06,0x1c,0x43,0xb0,0xa9,0x64,0x19,0x29,0x7d,0x5b,0xa1,0xd6,0xb3,0x2e,0x35,0x82,0x3a,0xd5,0xa0,0xf6,0xb4,0xb0,0x47,0x5d,0xa4,0x89,0x43,0xce,0x56,0x71,0x6c,0x34,0x18,0xce,0x0a,0x7d,0x1a,0x07},
+    {0x0b,0xba,0x87,0xc8,0xaa,0x2d,0x07,0xd3,0xee,0x62,0xa5,0xbf,0x05,0x29,0x26,0x01,0x8b,0x76,0xef,0xc0,0x02,0x30,0x54,0xcf,0x9c,0x7e,0xea,0x46,0x71,0xcc,0x3b,0x2c,0x31,0x44,0xe1,0x20,0x52,0x35,0x0c,0xcc,0x41,0x51,0xb1,0x09,0x07,0x95,0x65,0x0d,0x36,0x5f,0x9d,0x20,0x1b,0x62,0xf5,0x9a,0xd3,0x55,0x77,0x61,0xf7,0xbc,0x69,0x7c,0x5f,0x29,0xe8,0x04,0xeb,0xd7,0xf0,0x07,0x7d,0xf3,0x50,0x2f,0x25,0x18,0xdb,0x10,0xd7,0x98,0x17,0x17,0xa3,0xa9,0x51,0xe9,0x1d,0xa5,0xac,0x22,0x73,0x9a,0x5a,0x6f},
+    {0xc5,0xc6,0x41,0x2f,0x0c,0x00,0xa1,0x8b,0x9b,0xfb,0xfe,0x0c,0xc1,0x79,0x9f,0xc4,0x9f,0x1c,0xc5,0x3c,0x70,0x47,0xfa,0x4e,0xca,0xaf,0x47,0xe1,0xa2,0x21,0x4e,0x49,0xbe,0x44,0xd9,0xa3,0xeb,0xd4,0x29,0xe7,0x9e,0xaf,0x78,0x80,0x40,0x09,0x9e,0x8d,0x03,0x9c,0x86,0x47,0x7a,0x56,0x25,0x45,0x24,0x3b,0x8d,0xee,0x80,0x96,0xab,0x02,0x9a,0x0d,0xe5,0xdd,0x85,0x8a,0xa4,0xef,0x49,0xa2,0xb9,0x0f,0x4e,0x22,0x9a,0x21,0xd9,0xf6,0x1e,0xd9,0x1d,0x1f,0x09,0xfa,0x34,0xbb,0x46,0xea,0xcb,0x76,0x5d,0x6b},
+    {0x94,0xd9,0x0c,0xec,0x6c,0x55,0x57,0x88,0xba,0x1d,0xd0,0x5c,0x6f,0xdc,0x72,0x64,0x77,0xb4,0x42,0x8f,0x14,0x69,0x01,0xaf,0x54,0x73,0x27,0x85,0xf6,0x33,0xe3,0x0a,0x22,0x25,0x78,0x1e,0x17,0x41,0xf9,0xe0,0xd3,0x36,0x69,0x03,0x74,0xae,0xe6,0xf1,0x46,0xc7,0xfc,0xd0,0xa2,0x3e,0x8b,0x40,0x3e,0x31,0xdd,0x03,0x9c,0x86,0xfb,0x16,0x62,0x09,0xb6,0x33,0x97,0x19,0x8e,0x28,0x33,0xe1,0xab,0xd8,0xb4,0x72,0xfc,0x24,0x3e,0xd0,0x91,0x09,0xed,0xf7,0x11,0x48,0x75,0xd0,0x70,0x8f,0x8b,0xe3,0x81,0x3f},
+    {0xfe,0xaf,0xd9,0x7e,0xcc,0x0f,0x91,0x7f,0x4b,0x87,0x65,0x24,0xa1,0xb8,0x5c,0x54,0x04,0x47,0x0c,0x4b,0xd2,0x7e,0x39,0xa8,0x93,0x09,0xf5,0x04,0xc1,0x0f,0x51,0x50,0x24,0xc8,0x17,0x5f,0x35,0x7f,0xdb,0x0a,0xa4,0x99,0x42,0xd7,0xc3,0x23,0xb9,0x74,0xf7,0xea,0xf8,0xcb,0x8b,0x3e,0x7c,0xd5,0x3d,0xdc,0xde,0x4c,0xd3,0xe2,0xd3,0x0a,0x9d,0x24,0x6e,0x33,0xc5,0x0f,0x0c,0x6f,0xd9,0xcf,0x31,0xc3,0x19,0xde,0x5e,0x74,0x1c,0xfe,0xee,0x09,0x00,0xfd,0xd6,0xf2,0xbe,0x1e,0xfa,0xf0,0x8b,0x15,0x7c,0x12},
+    {0xa2,0x79,0x98,0x2e,0x42,0x7c,0x19,0xf6,0x47,0x36,0xca,0x52,0xd4,0xdd,0x4a,0xa4,0xcb,0xac,0x4e,0x4b,0xc1,0x3f,0x41,0x9b,0x68,0x4f,0xef,0x07,0x7d,0xf8,0x4e,0x35,0x74,0xb9,0x51,0xae,0xc4,0x8f,0xa2,0xde,0x96,0xfe,0x4d,0x74,0xd3,0x73,0x99,0x1d,0xa8,0x48,0x38,0x87,0x0b,0x68,0x40,0x62,0x95,0xdf,0x67,0xd1,0x79,0x24,0xd8,0x4e,0x75,0xd9,0xc5,0x60,0x22,0xb5,0xe3,0xfe,0xb8,0xb0,0x41,0xeb,0xfc,0x2e,0x35,0x50,0x3c,0x65,0xf6,0xa9,0x30,0xac,0x08,0x88,0x6d,0x23,0x39,0x05,0xd2,0x92,0x2d,0x30},
+    {0x3d,0x28,0xa4,0xbc,0xa2,0xc1,0x13,0x78,0xd9,0x3d,0x86,0xa1,0x91,0xf0,0x62,0xed,0x86,0xfa,0x68,0xc2,0xb8,0xbc,0xc7,0xae,0x4c,0xae,0x1c,0x6f,0xb7,0xd3,0xe5,0x10,0x77,0xf1,0xe0,0xe4,0xb6,0x6f,0xbc,0x2d,0x93,0x6a,0xbd,0xa4,0x29,0xbf,0xe1,0x04,0xe8,0xf6,0x7a,0x78,0xd4,0x66,0x19,0x5e,0x60,0xd0,0x26,0xb4,0x5e,0x5f,0xdc,0x0e,0x67,0x8e,0xda,0x53,0xd6,0xbf,0x53,0x54,0x41,0xf6,0xa9,0x24,0xec,0x1e,0xdc,0xe9,0x23,0x8a,0x57,0x03,0x3b,0x26,0x87,0xbf,0x72,0xba,0x1c,0x36,0x51,0x6c,0xb4,0x45},
+    {0xa1,0x7f,0x4f,0x31,0xbf,0x2a,0x40,0xa9,0x50,0xf4,0x8c,0x8e,0xdc,0xf1,0x57,0xe2,0x84,0xbe,0xa8,0x23,0x4b,0xd5,0xbb,0x1d,0x3b,0x71,0xcb,0x6d,0xa3,0xbf,0x77,0x21,0xe4,0xe3,0x7f,0x8a,0xdd,0x4d,0x9d,0xce,0x30,0x0e,0x62,0x76,0x56,0x64,0x13,0xab,0x58,0x99,0x0e,0xb3,0x7b,0x4f,0x59,0x4b,0xdf,0x29,0x12,0x32,0xef,0x0a,0x1c,0x5c,0x8f,0xdb,0x79,0xfa,0xbc,0x1b,0x08,0x37,0xb3,0x59,0x5f,0xc2,0x1e,0x81,0x48,0x60,0x87,0x24,0x83,0x9c,0x65,0x76,0x7a,0x08,0xbb,0xb5,0x8a,0x7d,0x38,0x19,0xe6,0x4a},
+    {0x2e,0xa3,0x44,0x53,0xaa,0xf6,0xdb,0x8d,0x78,0x40,0x1b,0xb4,0xb4,0xea,0x88,0x7d,0x60,0x0d,0x13,0x4a,0x97,0xeb,0xb0,0x5e,0x03,0x3e,0xbf,0x17,0x1b,0xd9,0x00,0x1a,0x83,0xfb,0x5b,0x98,0x44,0x7e,0x11,0x61,0x36,0x31,0x96,0x71,0x2a,0x46,0xe0,0xfc,0x4b,0x90,0x25,0xd4,0x48,0x34,0xac,0x83,0x64,0x3d,0xa4,0x5b,0xbe,0x5a,0x68,0x75,0xb2,0xf2,0x61,0xeb,0x33,0x09,0x96,0x6e,0x52,0x49,0xff,0xc9,0xa8,0x0f,0x3d,0x54,0x69,0x65,0xf6,0x7a,0x10,0x75,0x72,0xdf,0xaa,0xe6,0xb0,0x23,0xb6,0x29,0x55,0x13},
+    {0x18,0xd5,0xd1,0xad,0xd7,0xdb,0xf0,0x18,0x11,0x1f,0xc1,0xcf,0x88,0x78,0x9f,0x97,0x9b,0x75,0x14,0x71,0xf0,0xe1,0x32,0x87,0x01,0x3a,0xca,0x65,0x1a,0xb8,0xb5,0x79,0xfe,0x83,0x2e,0xe2,0xbc,0x16,0xc7,0xf5,0xc1,0x85,0x09,0xe8,0x19,0xeb,0x2b,0xb4,0xae,0x4a,0x25,0x14,0x37,0xa6,0x9d,0xec,0x13,0xa6,0x90,0x15,0x05,0xea,0x72,0x59,0x11,0x78,0x8f,0xdc,0x20,0xac,0xd4,0x0f,0xa8,0x4f,0x4d,0xac,0x94,0xd2,0x9a,0x9a,0x34,0x04,0x36,0xb3,0x64,0x2d,0x1b,0xc0,0xdb,0x3b,0x5f,0x90,0x95,0x9c,0x7e,0x4f},
+    {0x2e,0x30,0x81,0x57,0xbc,0x4b,0x67,0x62,0x0f,0xdc,0xad,0x89,0x39,0x0f,0x52,0xd8,0xc6,0xd9,0xfb,0x53,0xae,0x99,0x29,0x8c,0x4c,0x8e,0x63,0x2e,0xd9,0x3a,0x99,0x31,0xfe,0x99,0x52,0x35,0x3d,0x44,0xc8,0x71,0xd7,0xea,0xeb,0xdb,0x1c,0x3b,0xcd,0x8b,0x66,0x94,0xa4,0xf1,0x9e,0x49,0x92,0x80,0xc8,0xad,0x44,0xa1,0xc4,0xee,0x42,0x19,0x92,0x49,0x23,0xae,0x19,0x53,0xac,0x7d,0x92,0x3e,0xea,0x0c,0x91,0x3d,0x1b,0x2c,0x22,0x11,0x3c,0x25,0x94,0xe4,0x3c,0x55,0x75,0xca,0xf9,0x4e,0x31,0x65,0x0a,0x2a},
+    {0xc2,0x27,0xf9,0xf7,0x7f,0x93,0xb7,0x2d,0x35,0xa6,0xd0,0x17,0x06,0x1f,0x74,0xdb,0x76,0xaf,0x55,0x11,0xa2,0xf3,0x82,0x59,0xed,0x2d,0x7c,0x64,0x18,0xe2,0xf6,0x4c,0x3a,0x79,0x1c,0x3c,0xcd,0x1a,0x36,0xcf,0x3b,0xbc,0x35,0x5a,0xac,0xbc,0x9e,0x2f,0xab,0xa6,0xcd,0xa8,0xe9,0x60,0xe8,0x60,0x13,0x1a,0xea,0x6d,0x9b,0xc3,0x5d,0x05,0xb6,0x5b,0x8d,0xc2,0x7c,0x22,0x19,0xb1,0xab,0xff,0x4d,0x77,0xbc,0x4e,0xe2,0x07,0x89,0x2c,0xa3,0xe4,0xce,0x78,0x3c,0xa8,0xb6,0x24,0xaa,0x10,0x77,0x30,0x1a,0x12},
+    {0x97,0x4a,0x03,0x9f,0x5e,0x5d,0xdb,0xe4,0x2d,0xbc,0x34,0x30,0x09,0xfc,0x53,0xe1,0xb1,0xd3,0x51,0x95,0x91,0x46,0x05,0x46,0x2d,0xe5,0x40,0x7a,0x6c,0xc7,0x3f,0x33,0xc9,0x83,0x74,0xc7,0x3e,0x71,0x59,0xd6,0xaf,0x96,0x2b,0xb8,0x77,0xe0,0xbf,0x88,0xd3,0xbc,0x97,0x10,0x23,0x28,0x9e,0x28,0x9b,0x3a,0xed,0x6c,0x4a,0xb9,0x7b,0x52,0x2e,0x48,0x5b,0x99,0x2a,0x99,0x3d,0x56,0x01,0x38,0x38,0x6e,0x7c,0xd0,0x05,0x34,0xe5,0xd8,0x64,0x2f,0xde,0x35,0x50,0x48,0xf7,0xa9,0xa7,0x20,0x9b,0x06,0x89,0x6b},
+    {0x0d,0x22,0x70,0x62,0x41,0xa0,0x2a,0x81,0x4e,0x5b,0x24,0xf9,0xfa,0x89,0x5a,0x99,0x05,0xef,0x72,0x50,0xce,0xc4,0xad,0xff,0x73,0xeb,0x73,0xaa,0x03,0x21,0xbc,0x23,0x77,0xdb,0xc7,0xb5,0x8c,0xfa,0x82,0x40,0x55,0xc1,0x34,0xc7,0xf8,0x86,0x86,0x06,0x7e,0xa5,0xe7,0xf6,0xd9,0xc8,0xe6,0x29,0xcf,0x9b,0x63,0xa7,0x08,0xd3,0x73,0x04,0x05,0x9e,0x58,0x03,0x26,0x79,0xee,0xca,0x92,0xc4,0xdc,0x46,0x12,0x42,0x4b,0x2b,0x4f,0xa9,0x01,0xe6,0x74,0xef,0xa1,0x02,0x1a,0x34,0x04,0xde,0xbf,0x73,0x2f,0x10},
+    {0xc6,0x45,0x57,0x7f,0xab,0xb9,0x18,0xeb,0x90,0xc6,0x87,0x57,0xee,0x8a,0x3a,0x02,0xa9,0xaf,0xf7,0x2d,0xda,0x12,0x27,0xb7,0x3d,0x01,0x5c,0xea,0x25,0x7d,0x59,0x36,0x9a,0x1c,0x51,0xb5,0xe0,0xda,0xb4,0xa2,0x06,0xff,0xff,0x2b,0x29,0x60,0xc8,0x7a,0x34,0x42,0x50,0xf5,0x5d,0x37,0x1f,0x98,0x2d,0xa1,0x4e,0xda,0x25,0xd7,0x6b,0x3f,0xac,0x58,0x60,0x10,0x7b,0x8d,0x4d,0x73,0x5f,0x90,0xc6,0x6f,0x9e,0x57,0x40,0xd9,0x2d,0x93,0x02,0x92,0xf9,0xf8,0x66,0x64,0xd0,0xd6,0x60,0xda,0x19,0xcc,0x7e,0x7b},
+    {0x0d,0x69,0x5c,0x69,0x3c,0x37,0xc2,0x78,0x6e,0x90,0x42,0x06,0x66,0x2e,0x25,0xdd,0xd2,0x2b,0xe1,0x4a,0x44,0x44,0x1d,0x95,0x56,0x39,0x74,0x01,0x76,0xad,0x35,0x42,0x9b,0xfa,0x7c,0xa7,0x51,0x4a,0xae,0x6d,0x50,0x86,0xa3,0xe7,0x54,0x36,0x26,0x82,0xdb,0x82,0x2d,0x8f,0xcd,0xff,0xbb,0x09,0xba,0xca,0xf5,0x1b,0x66,0xdc,0xbe,0x03,0xf5,0x75,0x89,0x07,0x0d,0xcb,0x58,0x62,0x98,0xf2,0x89,0x91,0x54,0x42,0x29,0x49,0xe4,0x6e,0xe3,0xe2,0x23,0xb4,0xca,0xa0,0xa1,0x66,0xf0,0xcd,0xb0,0xe2,0x7c,0x0e},
+    {0xa3,0x85,0x8c,0xc4,0x3a,0x64,0x94,0xc4,0xad,0x39,0x61,0x3c,0xf4,0x1d,0x36,0xfd,0x48,0x4d,0xe9,0x3a,0xdd,0x17,0xdb,0x09,0x4a,0x67,0xb4,0x8f,0x5d,0x0a,0x6e,0x66,0xf9,0x70,0x4b,0xd9,0xdf,0xfe,0xa6,0xfe,0x2d,0xba,0xfc,0xc1,0x51,0xc0,0x30,0xf1,0x89,0xab,0x2f,0x7f,0x7e,0xd4,0x82,0x48,0xb5,0xee,0xec,0x8a,0x13,0x56,0x52,0x61,0x0d,0xcb,0x70,0x48,0x4e,0xf6,0xbb,0x2a,0x6b,0x8b,0x45,0xaa,0xf0,0xbc,0x65,0xcd,0x5d,0x98,0xe8,0x75,0xba,0x4e,0xbe,0x9a,0xe4,0xde,0x14,0xd5,0x10,0xc8,0x0b,0x7f},
+    {0x6f,0x13,0xf4,0x26,0xa4,0x6b,0x00,0xb9,0x35,0x30,0xe0,0x57,0x9e,0x36,0x67,0x8d,0x28,0x3c,0x46,0x4f,0xd9,0xdf,0xc8,0xcb,0xf5,0xdb,0xee,0xf8,0xbc,0x8d,0x1f,0x0d,0xa0,0x13,0x72,0x73,0xad,0x9d,0xac,0x83,0x98,0x2e,0xf7,0x2e,0xba,0xf8,0xf6,0x9f,0x57,0x69,0xec,0x43,0xdd,0x2e,0x1e,0x31,0x75,0xab,0xc5,0xde,0x7d,0x90,0x3a,0x1d,0xdc,0x81,0xd0,0x3e,0x31,0x93,0x16,0xba,0x80,0x34,0x1b,0x85,0xad,0x9f,0x32,0x29,0xcb,0x21,0x03,0x03,0x3c,0x01,0x28,0x01,0xe3,0xfd,0x1b,0xa3,0x44,0x1b,0x01,0x00},
+    {0x0c,0x6c,0xc6,0x3f,0x6c,0xa0,0xdf,0x3f,0xd2,0x0d,0xd6,0x4d,0x8e,0xe3,0x40,0x5d,0x71,0x4d,0x8e,0x26,0x38,0x8b,0xe3,0x7a,0xe1,0x57,0x83,0x6e,0x91,0x8d,0xc4,0x3a,0x5c,0xa7,0x0a,0x6a,0x69,0x1f,0x56,0x16,0x6a,0xbd,0x52,0x58,0x5c,0x72,0xbf,0xc1,0xad,0x66,0x79,0x9a,0x7f,0xdd,0xa8,0x11,0x26,0x10,0x85,0xd2,0xa2,0x88,0xd9,0x63,0x2e,0x23,0xbd,0xaf,0x53,0x07,0x12,0x00,0x83,0xf6,0xd8,0xfd,0xb8,0xce,0x2b,0xe9,0x91,0x2b,0xe7,0x84,0xb3,0x69,0x16,0xf8,0x66,0xa0,0x68,0x23,0x2b,0xd5,0xfa,0x33},
+    {0x16,0x1e,0xe4,0xc5,0xc6,0x49,0x06,0x54,0x35,0x77,0x3f,0x33,0x30,0x64,0xf8,0x0a,0x46,0xe7,0x05,0xf3,0xd2,0xfc,0xac,0xb2,0xa7,0xdc,0x56,0xa2,0x29,0xf4,0xc0,0x16,0xe8,0xcf,0x22,0xc4,0xd0,0xc8,0x2c,0x8d,0xcb,0x3a,0xa1,0x05,0x7b,0x4f,0x2b,0x07,0x6f,0xa5,0xf6,0xec,0xe6,0xb6,0xfe,0xa3,0xe2,0x71,0x0a,0xb9,0xcc,0x55,0xc3,0x3c,0x31,0x91,0x3e,0x90,0x43,0x94,0xb6,0xe9,0xce,0x37,0x56,0x7a,0xcb,0x94,0xa4,0xb8,0x44,0x92,0xba,0xba,0xa4,0xd1,0x7c,0xc8,0x68,0x75,0xae,0x6b,0x42,0xaf,0x1e,0x63},
+    {0x9f,0xfe,0x66,0xda,0x10,0x04,0xe9,0xb3,0xa6,0xe5,0x16,0x6c,0x52,0x4b,0xdd,0x85,0x83,0xbf,0xf9,0x1e,0x61,0x97,0x3d,0xbc,0xb5,0x19,0xa9,0x1e,0x8b,0x64,0x99,0x55,0xe8,0x0d,0x70,0xa3,0xb9,0x75,0xd9,0x47,0x52,0x05,0xf8,0xe2,0xfb,0xc5,0x80,0x72,0xe1,0x5d,0xe4,0x32,0x27,0x8f,0x65,0x53,0xb5,0x80,0x5f,0x66,0x7f,0x2c,0x1f,0x43,0x19,0x7b,0x8f,0x85,0x44,0x63,0x02,0xd6,0x4a,0x51,0xea,0xa1,0x2f,0x35,0xab,0x14,0xd7,0xa9,0x90,0x20,0x1a,0x44,0x00,0x89,0x26,0x3b,0x25,0x91,0x5f,0x71,0x04,0x7b},
+    {0x43,0xae,0xf6,0xac,0x28,0xbd,0xed,0x83,0xb4,0x7a,0x5c,0x7d,0x8b,0x7c,0x35,0x86,0x44,0x2c,0xeb,0xb7,0x69,0x47,0x40,0xc0,0x3f,0x58,0xf6,0xc2,0xf5,0x7b,0xb3,0x59,0xc6,0xba,0xe6,0xc4,0x80,0xc2,0x76,0xb3,0x0b,0x9b,0x1d,0x6d,0xdd,0xd3,0x0e,0x97,0x44,0xf9,0x0b,0x45,0x58,0x95,0x9a,0xb0,0x23,0xe2,0xcd,0x57,0xfa,0xac,0xd0,0x48,0x71,0xe6,0xab,0x7d,0xe4,0x26,0x0f,0xb6,0x37,0x3a,0x2f,0x62,0x97,0xa1,0xd1,0xf1,0x94,0x03,0x96,0xe9,0x7e,0xce,0x08,0x42,0xdb,0x3b,0x6d,0x33,0x91,0x41,0x23,0x16},
+    {0xf6,0x7f,0x26,0xf6,0xde,0x99,0xe4,0xb9,0x43,0x08,0x2c,0x74,0x7b,0xca,0x72,0x77,0xb1,0xf2,0xa4,0xe9,0x3f,0x15,0xa0,0x23,0x06,0x50,0xd0,0xd5,0xec,0xdf,0xdf,0x2c,0x40,0x86,0xf3,0x1f,0xd6,0x9c,0x49,0xdd,0xa0,0x25,0x36,0x06,0xc3,0x9b,0xcd,0x29,0xc3,0x3d,0xd7,0x3d,0x02,0xd8,0xe2,0x51,0x31,0x92,0x3b,0x20,0x7a,0x70,0x25,0x4a,0x6a,0xed,0xf6,0x53,0x8a,0x66,0xb7,0x2a,0xa1,0x70,0xd1,0x1d,0x58,0x42,0x42,0x30,0x61,0x01,0xe2,0x3a,0x4c,0x14,0x00,0x40,0xfc,0x49,0x8e,0x24,0x6d,0x89,0x21,0x57},
+    {0xae,0x1b,0x18,0xfd,0x17,0x55,0x6e,0x0b,0xb4,0x63,0xb9,0x2b,0x9f,0x62,0x22,0x90,0x25,0x46,0x06,0x32,0xe9,0xbc,0x09,0x55,0xda,0x13,0x3c,0xf6,0x74,0xdd,0x8e,0x57,0x4e,0xda,0xd0,0xa1,0x91,0x50,0x5d,0x28,0x08,0x3e,0xfe,0xb5,0xa7,0x6f,0xaa,0x4b,0xb3,0x93,0x93,0xe1,0x7c,0x17,0xe5,0x63,0xfd,0x30,0xb0,0xc4,0xaf,0x35,0xc9,0x03,0x3d,0x0c,0x2b,0x49,0xc6,0x76,0x72,0x99,0xfc,0x05,0xe2,0xdf,0xc4,0xc2,0xcc,0x47,0x3c,0x3a,0x62,0xdd,0x84,0x9b,0xd2,0xdc,0xa2,0xc7,0x88,0x02,0x59,0xab,0xc2,0x3e},
+    {0xb9,0x7b,0xd8,0xe4,0x7b,0xd2,0xa0,0xa1,0xed,0x1a,0x39,0x61,0xeb,0x4d,0x8b,0xa9,0x83,0x9b,0xcb,0x73,0xd0,0xdd,0xa0,0x99,0xce,0xca,0x0f,0x20,0x5a,0xc2,0xd5,0x2d,0xcb,0xd1,0x32,0xae,0x09,0x3a,0x21,0xa7,0xd5,0xc2,0xf5,0x40,0xdf,0x87,0x2b,0x0f,0x29,0xab,0x1e,0xe8,0xc6,0xa4,0xae,0x0b,0x5e,0xac,0xdb,0x6a,0x6c,0xf6,0x1b,0x0e,0x7e,0x88,0x2c,0x79,0xe9,0xd5,0xab,0xe2,0x5d,0x6d,0x92,0xcb,0x18,0x00,0x02,0x1a,0x1e,0x5f,0xae,0xba,0xcd,0x69,0xba,0xbf,0x5f,0x8f,0xe8,0x5a,0xb3,0x48,0x05,0x73},
+    {0xee,0xb8,0xa8,0xcb,0xa3,0x51,0x35,0xc4,0x16,0x5f,0x11,0xb2,0x1d,0x6f,0xa2,0x65,0x50,0x38,0x8c,0xab,0x52,0x4f,0x0f,0x76,0xca,0xb8,0x1d,0x41,0x3b,0x44,0x43,0x30,0x34,0xe3,0xd6,0xa1,0x4b,0x09,0x5b,0x80,0x19,0x3f,0x35,0x09,0x77,0xf1,0x3e,0xbf,0x2b,0x70,0x22,0x06,0xcb,0x06,0x3f,0x42,0xdd,0x45,0x78,0xd8,0x77,0x22,0x5a,0x58,0x62,0x89,0xd4,0x33,0x82,0x5f,0x8a,0xa1,0x7f,0x25,0x78,0xec,0xb5,0xc4,0x98,0x66,0xff,0x41,0x3e,0x37,0xa5,0x6f,0x8e,0xa7,0x1f,0x98,0xef,0x50,0x89,0x27,0x56,0x76},
+    {0xc0,0xc8,0x1f,0xd5,0x59,0xcf,0xc3,0x38,0xf2,0xb6,0x06,0x05,0xfd,0xd2,0xed,0x9b,0x8f,0x0e,0x57,0xab,0x9f,0x10,0xbf,0x26,0xa6,0x46,0xb8,0xc1,0xa8,0x60,0x41,0x3f,0x9d,0xcf,0x86,0xea,0xa3,0x73,0x70,0xe1,0xdc,0x5f,0x15,0x07,0xb7,0xfb,0x8c,0x3a,0x8e,0x8a,0x83,0x31,0xfc,0xe7,0x53,0x48,0x16,0xf6,0x13,0xb6,0x84,0xf4,0xbb,0x28,0x7c,0x6c,0x13,0x6f,0x5c,0x2f,0x61,0xf2,0xbe,0x11,0xdd,0xf6,0x07,0xd1,0xea,0xaf,0x33,0x6f,0xde,0x13,0xd2,0x9a,0x7e,0x52,0x5d,0xf7,0x88,0x81,0x35,0xcb,0x79,0x1e},
+    {0xf1,0xe3,0xf7,0xee,0xc3,0x36,0x34,0x01,0xf8,0x10,0x9e,0xfe,0x7f,0x6a,0x8b,0x82,0xfc,0xde,0xf9,0xbc,0xe5,0x08,0xf9,0x7f,0x31,0x38,0x3b,0x3a,0x1b,0x95,0xd7,0x65,0x81,0x81,0xe0,0xf5,0xd8,0x53,0xe9,0x77,0xd9,0xde,0x9d,0x29,0x44,0x0c,0xa5,0x84,0xe5,0x25,0x45,0x86,0x0c,0x2d,0x6c,0xdc,0xf4,0xf2,0xd1,0x39,0x2d,0xb5,0x8a,0x47,0x59,0xd1,0x52,0x92,0xd3,0xa4,0xa6,0x66,0x07,0xc8,0x1a,0x87,0xbc,0xe1,0xdd,0xe5,0x6f,0xc9,0xc1,0xa6,0x40,0x6b,0x2c,0xb8,0x14,0x22,0x21,0x1a,0x41,0x7a,0xd8,0x16},
+    {0x15,0x62,0x06,0x42,0x5a,0x7e,0xbd,0xb3,0xc1,0x24,0x5a,0x0c,0xcd,0xe3,0x9b,0x87,0xb7,0x94,0xf9,0xd6,0xb1,0x5d,0xc0,0x57,0xa6,0x8c,0xf3,0x65,0x81,0x7c,0xf8,0x28,0x83,0x05,0x4e,0xd5,0xe2,0xd5,0xa4,0xfb,0xfa,0x99,0xbd,0x2e,0xd7,0xaf,0x1f,0xe2,0x8f,0x77,0xe9,0x6e,0x73,0xc2,0x7a,0x49,0xde,0x6d,0x5a,0x7a,0x57,0x0b,0x99,0x1f,0xd6,0xf7,0xe8,0x1b,0xad,0x4e,0x34,0xa3,0x8f,0x79,0xea,0xac,0xeb,0x50,0x1e,0x7d,0x52,0xe0,0x0d,0x52,0x9e,0x56,0xc6,0x77,0x3e,0x6d,0x4d,0x53,0xe1,0x2f,0x88,0x45},
+    {0xd6,0x83,0x79,0x75,0x5d,0x34,0x69,0x66,0xa6,0x11,0xaa,0x17,0x11,0xed,0xb6,0x62,0x8f,0x12,0x5e,0x98,0x57,0x18,0xdd,0x7d,0xdd,0xf6,0x26,0xf6,0xb8,0xe5,0x8f,0x68,0xe4,0x6f,0x3c,0x94,0x29,0x99,0xac,0xd8,0xa2,0x92,0x83,0xa3,0x61,0xf1,0xf9,0xb5,0xf3,0x9a,0xc8,0xbe,0x13,0xdb,0x99,0x26,0x74,0xf0,0x05,0xe4,0x3c,0x84,0xcf,0x7d,0xc0,0x32,0x47,0x4a,0x48,0xd6,0x90,0x6c,0x99,0x32,0x56,0xca,0xfd,0x43,0x21,0xd5,0xe1,0xc6,0x5d,0x91,0xc3,0x28,0xbe,0xb3,0x1b,0x19,0x27,0x73,0x7e,0x68,0x39,0x67},
+    {0xa6,0x75,0x56,0x38,0x14,0x20,0x78,0xef,0xe8,0xa9,0xfd,0xaa,0x30,0x9f,0x64,0xa2,0xcb,0xa8,0xdf,0x5c,0x50,0xeb,0xd1,0x4c,0xb3,0xc0,0x4d,0x1d,0xba,0x5a,0x11,0x46,0xc0,0x1a,0x0c,0xc8,0x9d,0xcc,0x6d,0xa6,0x36,0xa4,0x38,0x1b,0xf4,0x5c,0xa0,0x97,0xc6,0xd7,0xdb,0x95,0xbe,0xf3,0xeb,0xa7,0xab,0x7d,0x7e,0x8d,0xf6,0xb8,0xa0,0x7d,0x76,0xda,0xb5,0xc3,0x53,0x19,0x0f,0xd4,0x9b,0x9e,0x11,0x21,0x73,0x6f,0xac,0x1d,0x60,0x59,0xb2,0xfe,0x21,0x60,0xcc,0x03,0x4b,0x4b,0x67,0x83,0x7e,0x88,0x5f,0x5a},
+    {0x11,0x3d,0xa1,0x70,0xcf,0x01,0x63,0x8f,0xc4,0xd0,0x0d,0x35,0x15,0xb8,0xce,0xcf,0x7e,0xa4,0xbc,0xa4,0xd4,0x97,0x02,0xf7,0x34,0x14,0x4d,0xe4,0x56,0xb6,0x69,0x36,0xb9,0x43,0xa6,0xa0,0xd3,0x28,0x96,0x9e,0x64,0x20,0xc3,0xe6,0x00,0xcb,0xc3,0xb5,0x32,0xec,0x2d,0x7c,0x89,0x02,0x53,0x9b,0x0c,0xc7,0xd1,0xd5,0xe2,0x7a,0xe3,0x43,0x33,0xe1,0xa6,0xed,0x06,0x3f,0x7e,0x38,0xc0,0x3a,0xa1,0x99,0x51,0x1d,0x30,0x67,0x11,0x38,0x26,0x36,0xf8,0xd8,0x5a,0xbd,0xbe,0xe9,0xd5,0x4f,0xcd,0xe6,0x21,0x6a},
+    {0x5f,0xe6,0x46,0x30,0x0a,0x17,0xc6,0xf1,0x24,0x35,0xd2,0x00,0x2a,0x2a,0x71,0x58,0x55,0xb7,0x82,0x8c,0x3c,0xbd,0xdb,0x69,0x57,0xff,0x95,0xa1,0xf1,0xf9,0x6b,0x58,0xe3,0xb2,0x99,0x66,0x12,0x29,0x41,0xef,0x01,0x13,0x8d,0x70,0x47,0x08,0xd3,0x71,0xbd,0xb0,0x82,0x11,0xd0,0x32,0x54,0x32,0x36,0x8b,0x1e,0x00,0x07,0x1b,0x37,0x45,0x0b,0x79,0xf8,0x5e,0x8d,0x08,0xdb,0xa6,0xe5,0x37,0x09,0x61,0xdc,0xf0,0x78,0x52,0xb8,0x6e,0xa1,0x61,0xd2,0x49,0x03,0xac,0x79,0x21,0xe5,0x90,0x37,0xb0,0xaf,0x0e},
+    {0x2f,0x04,0x48,0x37,0xc1,0x55,0x05,0x96,0x11,0xaa,0x0b,0x82,0xe6,0x41,0x9a,0x21,0x0c,0x6d,0x48,0x73,0x38,0xf7,0x81,0x1c,0x61,0xc6,0x02,0x5a,0x67,0xcc,0x9a,0x30,0x1d,0xae,0x75,0x0f,0x5e,0x80,0x40,0x51,0x30,0xcc,0x62,0x26,0xe3,0xfb,0x02,0xec,0x6d,0x39,0x92,0xea,0x1e,0xdf,0xeb,0x2c,0xb3,0x5b,0x43,0xc5,0x44,0x33,0xae,0x44,0xee,0x43,0xa5,0xbb,0xb9,0x89,0xf2,0x9c,0x42,0x71,0xc9,0x5a,0x9d,0x0e,0x76,0xf3,0xaa,0x60,0x93,0x4f,0xc6,0xe5,0x82,0x1d,0x8f,0x67,0x94,0x7f,0x1b,0x22,0xd5,0x62},
+    {0x6d,0x93,0xd0,0x18,0x9c,0x29,0x4c,0x52,0x0c,0x1a,0x0c,0x8a,0x6c,0xb5,0x6b,0xc8,0x31,0x86,0x4a,0xdb,0x2e,0x05,0x75,0xa3,0x62,0x45,0x75,0xbc,0xe4,0xfd,0x0e,0x5c,0x3c,0x7a,0xf7,0x3a,0x26,0xd4,0x85,0x75,0x4d,0x14,0xe9,0xfe,0x11,0x7b,0xae,0xdf,0x3d,0x19,0xf7,0x59,0x80,0x70,0x06,0xa5,0x37,0x20,0x92,0x83,0x53,0x9a,0xf2,0x14,0xf5,0xd7,0xb2,0x25,0xdc,0x7e,0x71,0xdf,0x40,0x30,0xb5,0x99,0xdb,0x70,0xf9,0x21,0x62,0x4c,0xed,0xc3,0xb7,0x34,0x92,0xda,0x3e,0x09,0xee,0x7b,0x5c,0x36,0x72,0x5e},
+    {0x7f,0x21,0x71,0x45,0x07,0xfc,0x5b,0x57,0x5b,0xd9,0x94,0x06,0x5d,0x67,0x79,0x37,0x33,0x1e,0x19,0xf4,0xbb,0x37,0x0a,0x9a,0xbc,0xea,0xb4,0x47,0x4c,0x10,0xf1,0x77,0x3e,0xb3,0x08,0x2f,0x06,0x39,0x93,0x7d,0xbe,0x32,0x9f,0xdf,0xe5,0x59,0x96,0x5b,0xfd,0xbd,0x9e,0x1f,0xad,0x3d,0xff,0xac,0xb7,0x49,0x73,0xcb,0x55,0x05,0xb2,0x70,0x4c,0x2c,0x11,0x55,0xc5,0x13,0x51,0xbe,0xcd,0x1f,0x88,0x9a,0x3a,0x42,0x88,0x66,0x47,0x3b,0x50,0x5e,0x85,0x77,0x66,0x44,0x4a,0x40,0x06,0x4a,0x8f,0x39,0x34,0x0e},
+    {0xe8,0xbd,0xce,0x3e,0xd9,0x22,0x7d,0xb6,0x07,0x2f,0x82,0x27,0x41,0xe8,0xb3,0x09,0x8d,0x6d,0x5b,0xb0,0x1f,0xa6,0x3f,0x74,0x72,0x23,0x36,0x8a,0x36,0x05,0x54,0x5e,0x28,0x19,0x4b,0x3e,0x09,0x0b,0x93,0x18,0x40,0xf6,0xf3,0x73,0x0e,0xe1,0xe3,0x7d,0x6f,0x5d,0x39,0x73,0xda,0x17,0x32,0xf4,0x3e,0x9c,0x37,0xca,0xd6,0xde,0x8a,0x6f,0x9a,0xb2,0xb7,0xfd,0x3d,0x12,0x40,0xe3,0x91,0xb2,0x1a,0xa2,0xe1,0x97,0x7b,0x48,0x9e,0x94,0xe6,0xfd,0x02,0x7d,0x96,0xf9,0x97,0xde,0xd3,0xc8,0x2e,0xe7,0x0d,0x78},
+    {0xbc,0xe7,0x9a,0x08,0x45,0x85,0xe2,0x0a,0x06,0x4d,0x7f,0x1c,0xcf,0xde,0x8d,0x38,0xb8,0x11,0x48,0x0a,0x51,0x15,0xac,0x38,0xe4,0x8c,0x92,0x71,0xf6,0x8b,0xb2,0x0e,0x72,0x27,0xf4,0x00,0xf3,0xea,0x1f,0x67,0xaa,0x41,0x8c,0x2a,0x2a,0xeb,0x72,0x8f,0x92,0x32,0x37,0x97,0xd7,0x7f,0xa1,0x29,0xa6,0x87,0xb5,0x32,0xad,0xc6,0xef,0x1d,0xa7,0x95,0x51,0xef,0x1a,0xbe,0x5b,0xaf,0xed,0x15,0x7b,0x91,0x77,0x12,0x8c,0x14,0x2e,0xda,0xe5,0x7a,0xfb,0xf7,0x91,0x29,0x67,0x28,0xdd,0xf8,0x1b,0x20,0x7d,0x46},
+    {0xad,0x4f,0xef,0x74,0x9a,0x91,0xfe,0x95,0xa2,0x08,0xa3,0xf6,0xec,0x7b,0x82,0x3a,0x01,0x7b,0xa4,0x09,0xd3,0x01,0x4e,0x96,0x97,0xc7,0xa3,0x5b,0x4f,0x3c,0xc4,0x71,0xa9,0xe7,0x7a,0x56,0xbd,0xf4,0x1e,0xbc,0xbd,0x98,0x44,0xd6,0xb2,0x4c,0x62,0x3f,0xc8,0x4e,0x1f,0x2c,0xd2,0x64,0x10,0xe4,0x01,0x40,0x38,0xba,0xa5,0xc5,0xf9,0x2e,0xcd,0x74,0x9e,0xfa,0xf6,0x6d,0xfd,0xb6,0x7a,0x26,0xaf,0xe4,0xbc,0x78,0x82,0xf1,0x0e,0x99,0xef,0xf1,0xd0,0xb3,0x55,0x82,0x93,0xf2,0xc5,0x90,0xa3,0x8c,0x75,0x5a},
+    {0x95,0x24,0x46,0xd9,0x10,0x27,0xb7,0xa2,0x03,0x50,0x7d,0xd5,0xd2,0xc6,0xa8,0x3a,0xca,0x87,0xb4,0xa0,0xbf,0x00,0xd4,0xe3,0xec,0x72,0xeb,0xb3,0x44,0xe2,0xba,0x2d,0x94,0xdc,0x61,0x1d,0x8b,0x91,0xe0,0x8c,0x66,0x30,0x81,0x9a,0x46,0x36,0xed,0x8d,0xd3,0xaa,0xe8,0xaf,0x29,0xa8,0xe6,0xd4,0x3f,0xd4,0x39,0xf6,0x27,0x80,0x73,0x0a,0xcc,0xe1,0xff,0x57,0x2f,0x4a,0x0f,0x98,0x43,0x98,0x83,0xe1,0x0d,0x0d,0x67,0x00,0xfd,0x15,0xfb,0x49,0x4a,0x3f,0x5c,0x10,0x9c,0xa6,0x26,0x51,0x63,0xca,0x98,0x26},
+    {0x78,0xba,0xb0,0x32,0x88,0x31,0x65,0xe7,0x8b,0xff,0x5c,0x92,0xf7,0x31,0x18,0x38,0xcc,0x1f,0x29,0xa0,0x91,0x1b,0xa8,0x08,0x07,0xeb,0xca,0x49,0xcc,0x3d,0xb4,0x1f,0x0e,0xd9,0x3d,0x5e,0x2f,0x70,0x3d,0x2e,0x86,0x53,0xd2,0xe4,0x18,0x09,0x3f,0x9e,0x6a,0xa9,0x4d,0x02,0xf6,0x3e,0x77,0x5e,0x32,0x33,0xfa,0x4a,0x0c,0x4b,0x00,0x3c,0x2b,0xb8,0xf4,0x06,0xac,0x46,0xa9,0x9a,0xf3,0xc4,0x06,0xa8,0xa5,0x84,0xa2,0x1c,0x87,0x47,0xcd,0xc6,0x5f,0x26,0xd3,0x3e,0x17,0xd2,0x1f,0xcd,0x01,0xfd,0x43,0x6b},
+    {0x44,0xc5,0x97,0x46,0x4b,0x5d,0xa7,0xc7,0xbf,0xff,0x0f,0xdf,0x48,0xf8,0xfd,0x15,0x5a,0x78,0x46,0xaa,0xeb,0xb9,0x68,0x28,0x14,0xf7,0x52,0x5b,0x10,0xd7,0x68,0x5a,0xf3,0x0e,0x76,0x3e,0x58,0x42,0xc7,0xb5,0x90,0xb9,0x0a,0xee,0xb9,0x52,0xdc,0x75,0x3f,0x92,0x2b,0x07,0xc2,0x27,0x14,0xbf,0xf0,0xd9,0xf0,0x6f,0x2d,0x0b,0x42,0x73,0x06,0x1e,0x85,0x9e,0xcb,0xf6,0x2c,0xaf,0xc4,0x38,0x22,0xc6,0x13,0x39,0x59,0x8f,0x73,0xf3,0xfb,0x99,0x96,0xb8,0x8a,0xda,0x9e,0xbc,0x34,0xea,0x2f,0x63,0xb5,0x3d},
+    {0xd8,0xd9,0x5d,0xf7,0x2b,0xee,0x6e,0xf4,0xa5,0x59,0x67,0x39,0xf6,0xb1,0x17,0x0d,0x73,0x72,0x9e,0x49,0x31,0xd1,0xf2,0x1b,0x13,0x5f,0xd7,0x49,0xdf,0x1a,0x32,0x04,0xd5,0x25,0x98,0x82,0xb1,0x90,0x49,0x2e,0x91,0x89,0x9a,0x3e,0x87,0xeb,0xea,0xed,0xf8,0x4a,0x70,0x4c,0x39,0x3d,0xf0,0xee,0x0e,0x2b,0xdf,0x95,0xa4,0x7e,0x19,0x59,0xae,0x5a,0xe5,0xe4,0x19,0x60,0xe1,0x04,0xe9,0x92,0x2f,0x7e,0x7a,0x43,0x7b,0xe7,0xa4,0x9a,0x15,0x6f,0xc1,0x2d,0xce,0xc7,0xc0,0x0c,0xd7,0xf4,0xc1,0xfd,0xea,0x45},
+    {0x2b,0xd7,0x45,0x80,0x85,0x01,0x84,0x69,0x51,0x06,0x2f,0xcf,0xa2,0xfa,0x22,0x4c,0xc6,0x2d,0x22,0x6b,0x65,0x36,0x1a,0x94,0xde,0xda,0x62,0x03,0xc8,0xeb,0x5e,0x5a,0xed,0xb1,0xcc,0xcf,0x24,0x46,0x0e,0xb6,0x95,0x03,0x5c,0xbd,0x92,0xc2,0xdb,0x59,0xc9,0x81,0x04,0xdc,0x1d,0x9d,0xa0,0x31,0x40,0xd9,0x56,0x5d,0xea,0xce,0x73,0x3f,0xc6,0x8d,0x4e,0x0a,0xd1,0xbf,0xa7,0xb7,0x39,0xb3,0xc9,0x44,0x7e,0x00,0x57,0xbe,0xfa,0xae,0x57,0x15,0x7f,0x20,0xc1,0x60,0xdb,0x18,0x62,0x26,0x91,0x88,0x05,0x26},
+    {0x04,0xff,0x60,0x83,0xa6,0x04,0xf7,0x59,0xf4,0xe6,0x61,0x76,0xde,0x3f,0xd9,0xc3,0x51,0x35,0x87,0x12,0x73,0x2a,0x1b,0x83,0x57,0x5d,0x61,0x4e,0x2e,0x0c,0xad,0x54,0x42,0xe5,0x76,0xc6,0x3c,0x8e,0x81,0x4c,0xad,0xcc,0xce,0x03,0x93,0x2c,0x42,0x5e,0x08,0x9f,0x12,0xb4,0xca,0xcc,0x07,0xec,0xb8,0x43,0x44,0xb2,0x10,0xfa,0xed,0x0d,0x2a,0x52,0x2b,0xb8,0xd5,0x67,0x3b,0xee,0xeb,0xc1,0xa5,0x9f,0x46,0x63,0xf1,0x36,0xd3,0x9f,0xc1,0x6e,0xf2,0xd2,0xb4,0xa5,0x08,0x94,0x7a,0xa7,0xba,0xb2,0xec,0x62},
+    {0x3d,0x2b,0x15,0x61,0x52,0x79,0xed,0xe5,0xd1,0xd7,0xdd,0x0e,0x7d,0x35,0x62,0x49,0x71,0x4c,0x6b,0xb9,0xd0,0xc8,0x82,0x74,0xbe,0xd8,0x66,0xa9,0x19,0xf9,0x59,0x2e,0x74,0x28,0xb6,0xaf,0x36,0x28,0x07,0x92,0xa5,0x04,0xe1,0x79,0x85,0x5e,0xcd,0x5f,0x4a,0xa1,0x30,0xc6,0xad,0x01,0xad,0x5a,0x98,0x3f,0x66,0x75,0x50,0x3d,0x91,0x61,0xda,0x31,0x32,0x1a,0x36,0x2d,0xc6,0x0d,0x70,0x02,0x20,0x94,0x32,0x58,0x47,0xfa,0xce,0x94,0x95,0x3f,0x51,0x01,0xd8,0x02,0x5c,0x5d,0xc0,0x31,0xa1,0xc2,0xdb,0x3d},
+    {0x4b,0xc5,0x5e,0xce,0xf9,0x0f,0xdc,0x9a,0x0d,0x13,0x2f,0x8c,0x6b,0x2a,0x9c,0x03,0x15,0x95,0xf8,0xf0,0xc7,0x07,0x80,0x02,0x6b,0xb3,0x04,0xac,0x14,0x83,0x96,0x78,0x14,0xbb,0x96,0x27,0xa2,0x57,0xaa,0xf3,0x21,0xda,0x07,0x9b,0xb7,0xba,0x3a,0x88,0x1c,0x39,0xa0,0x31,0x18,0xe2,0x4b,0xe5,0xf9,0x05,0x32,0xd8,0x38,0xfb,0xe7,0x5e,0x8e,0x6a,0x44,0x41,0xcb,0xfd,0x8d,0x53,0xf9,0x37,0x49,0x43,0xa9,0xfd,0xac,0xa5,0x78,0x8c,0x3c,0x26,0x8d,0x90,0xaf,0x46,0x09,0x0d,0xca,0x9b,0x3c,0x63,0xd0,0x61},
+    {0x66,0x25,0xdb,0xff,0x35,0x49,0x74,0x63,0xbb,0x68,0x0b,0x78,0x89,0x6b,0xbd,0xc5,0x03,0xec,0x3e,0x55,0x80,0x32,0x1b,0x6f,0xf5,0xd7,0xae,0x47,0xd8,0x5f,0x96,0x6e,0xdf,0x73,0xfc,0xf8,0xbc,0x28,0xa3,0xad,0xfc,0x37,0xf0,0xa6,0x5d,0x69,0x84,0xee,0x09,0xa9,0xc2,0x38,0xdb,0xb4,0x7f,0x63,0xdc,0x7b,0x06,0xf8,0x2d,0xac,0x23,0x5b,0x7b,0x52,0x80,0xee,0x53,0xb9,0xd2,0x9a,0x8d,0x6d,0xde,0xfa,0xaa,0x19,0x8f,0xe8,0xcf,0x82,0x0e,0x15,0x04,0x17,0x71,0x0e,0xdc,0xde,0x95,0xdd,0xb9,0xbb,0xb9,0x79},
+    {0xc2,0x26,0x31,0x6a,0x40,0x55,0xb3,0xeb,0x93,0xc3,0xc8,0x68,0xa8,0x83,0x63,0xd2,0x82,0x7a,0xb9,0xe5,0x29,0x64,0x0c,0x6c,0x47,0x21,0xfd,0xc9,0x58,0xf1,0x65,0x50,0x74,0x73,0x9f,0x8e,0xae,0x7d,0x99,0xd1,0x16,0x08,0xbb,0xcf,0xf8,0xa2,0x32,0xa0,0x0a,0x5f,0x44,0x6d,0x12,0xba,0x6c,0xcd,0x34,0xb8,0xcc,0x0a,0x46,0x11,0xa8,0x1b,0x54,0x99,0x42,0x0c,0xfb,0x69,0x81,0x70,0x67,0xcf,0x6e,0xd7,0xac,0x00,0x46,0xe1,0xba,0x45,0xe6,0x70,0x8a,0xb9,0xaa,0x2e,0xf2,0xfa,0xa4,0x58,0x9e,0xf3,0x81,0x39},
+    {0x93,0x0a,0x23,0x59,0x75,0x8a,0xfb,0x18,0x5d,0xf4,0xe6,0x60,0x69,0x8f,0x16,0x1d,0xb5,0x3c,0xa9,0x14,0x45,0xa9,0x85,0x3a,0xfd,0xd0,0xac,0x05,0x37,0x08,0xdc,0x38,0xde,0x6f,0xe6,0x6d,0xa5,0xdf,0x45,0xc8,0x3a,0x48,0x40,0x2c,0x00,0xa5,0x52,0xe1,0x32,0xf6,0xb4,0xc7,0x63,0xe1,0xd2,0xe9,0x65,0x1b,0xbc,0xdc,0x2e,0x45,0xf4,0x30,0x40,0x97,0x75,0xc5,0x82,0x27,0x6d,0x85,0xcc,0xbe,0x9c,0xf9,0x69,0x45,0x13,0xfa,0x71,0x4e,0xea,0xc0,0x73,0xfc,0x44,0x88,0x69,0x24,0x3f,0x59,0x1a,0x9a,0x2d,0x63},
+    {0xa6,0xcb,0x07,0xb8,0x15,0x6b,0xbb,0xf6,0xd7,0xf0,0x54,0xbc,0xdf,0xc7,0x23,0x18,0x0b,0x67,0x29,0x6e,0x03,0x97,0x1d,0xbb,0x57,0x4a,0xed,0x47,0x88,0xf4,0x24,0x0b,0xa7,0x84,0x0c,0xed,0x11,0xfd,0x09,0xbf,0x3a,0x69,0x9f,0x0d,0x81,0x71,0xf0,0x63,0x79,0x87,0xcf,0x57,0x2d,0x8c,0x90,0x21,0xa2,0x4b,0xf6,0x8a,0xf2,0x7d,0x5a,0x3a,0xc7,0xea,0x1b,0x51,0xbe,0xd4,0xda,0xdc,0xf2,0xcc,0x26,0xed,0x75,0x80,0x53,0xa4,0x65,0x9a,0x5f,0x00,0x9f,0xff,0x9c,0xe1,0x63,0x1f,0x48,0x75,0x44,0xf7,0xfc,0x34},
+    {0xca,0x67,0x97,0x78,0x4c,0xe0,0x97,0xc1,0x7d,0x46,0xd9,0x38,0xcb,0x4d,0x71,0xb8,0xa8,0x5f,0xf9,0x83,0x82,0x88,0xde,0x55,0xf7,0x63,0xfa,0x4d,0x16,0xdc,0x3b,0x3d,0x98,0xaa,0xcf,0x78,0xab,0x1d,0xbb,0xa5,0xf2,0x72,0x0b,0x19,0x67,0xa2,0xed,0x5c,0x8e,0x60,0x92,0x0a,0x11,0xc9,0x09,0x93,0xb0,0x74,0xb3,0x2f,0x04,0xa3,0x19,0x01,0x7d,0x17,0xc2,0xe8,0x9c,0xd8,0xa2,0x67,0xc1,0xd0,0x95,0x68,0xf6,0xa5,0x9d,0x66,0xb0,0xa2,0x82,0xb2,0xe5,0x98,0x65,0xf5,0x73,0x0a,0xe2,0xed,0xf1,0x88,0xc0,0x56},
+    {0x17,0x6e,0xa8,0x10,0x11,0x3d,0x6d,0x33,0xfa,0xb2,0x75,0x0b,0x32,0x88,0xf3,0xd7,0x88,0x29,0x07,0x25,0x76,0x33,0x15,0xf9,0x87,0x8b,0x10,0x99,0x6b,0x4c,0x67,0x09,0x02,0x8f,0xf3,0x24,0xac,0x5f,0x1b,0x58,0xbd,0x0c,0xe3,0xba,0xfe,0xe9,0x0b,0xa9,0xf0,0x92,0xcf,0x8a,0x02,0x69,0x21,0x9a,0x8f,0x03,0x59,0x83,0xa4,0x7e,0x8b,0x03,0xf8,0x6f,0x31,0x99,0x21,0xf8,0x4e,0x9f,0x4f,0x8d,0xa7,0xea,0x82,0xd2,0x49,0x2f,0x74,0x31,0xef,0x5a,0xab,0xa5,0x71,0x09,0x65,0xeb,0x69,0x59,0x02,0x31,0x5e,0x6e},
+    {0xfb,0x93,0xe5,0x87,0xf5,0x62,0x6c,0xb1,0x71,0x3e,0x5d,0xca,0xde,0xed,0x99,0x49,0x6d,0x3e,0xcc,0x14,0xe0,0xc1,0x91,0xb4,0xa8,0xdb,0xa8,0x89,0x47,0x11,0xf5,0x08,0x22,0x62,0x06,0x63,0x0e,0xfb,0x04,0x33,0x3f,0xba,0xac,0x87,0x89,0x06,0x35,0xfb,0xa3,0x61,0x10,0x8c,0x77,0x24,0x19,0xbd,0x20,0x86,0x83,0xd1,0x43,0xad,0x58,0x30,0xd0,0x63,0x76,0xe5,0xfd,0x0f,0x3c,0x32,0x10,0xa6,0x2e,0xa2,0x38,0xdf,0xc3,0x05,0x9a,0x4f,0x99,0xac,0xbd,0x8a,0xc7,0xbd,0x99,0xdc,0xe3,0xef,0xa4,0x9f,0x54,0x26},
+    {0xd6,0xf9,0x6b,0x1e,0x46,0x5a,0x1d,0x74,0x81,0xa5,0x77,0x77,0xfc,0xb3,0x05,0x23,0xd9,0xd3,0x74,0x64,0xa2,0x74,0x55,0xd4,0xff,0xe0,0x01,0x64,0xdc,0xe1,0x26,0x19,0x6e,0x66,0x3f,0xaf,0x49,0x85,0x46,0xdb,0xa5,0x0e,0x4a,0xf1,0x04,0xcf,0x7f,0xd7,0x47,0x0c,0xba,0xa4,0xf7,0x3f,0xf2,0x3d,0x85,0x3c,0xce,0x32,0xe1,0xdf,0x10,0x3a,0xa0,0xce,0x17,0xea,0x8a,0x4e,0x7f,0xe0,0xfd,0xc1,0x1f,0x3a,0x46,0x15,0xd5,0x2f,0xf1,0xc0,0xf2,0x31,0xfd,0x22,0x53,0x17,0x15,0x5d,0x1e,0x86,0x1d,0xd0,0xa1,0x1f},
+    {0x32,0x98,0x59,0x7d,0x94,0x55,0x80,0xcc,0x20,0x55,0xf1,0x37,0xda,0x56,0x46,0x1e,0x20,0x93,0x05,0x4e,0x74,0xf7,0xf6,0x99,0x33,0xcf,0x75,0x6a,0xbc,0x63,0x35,0x77,0xab,0x94,0xdf,0xd1,0x00,0xac,0xdc,0x38,0xe9,0x0d,0x08,0xd1,0xdd,0x2b,0x71,0x2e,0x62,0xe2,0xd5,0xfd,0x3e,0xe9,0x13,0x7f,0xe5,0x01,0x9a,0xee,0x18,0xed,0xfc,0x73,0xb3,0x9c,0x13,0x63,0x08,0xe9,0xb1,0x06,0xcd,0x3e,0xa0,0xc5,0x67,0xda,0x93,0xa4,0x32,0x89,0x63,0xad,0xc8,0xce,0x77,0x8d,0x44,0x4f,0x86,0x1b,0x70,0x6b,0x42,0x1f},
+    {0x01,0x1c,0x91,0x41,0x4c,0x26,0xc9,0xef,0x25,0x2c,0xa2,0x17,0xb8,0xb7,0xa3,0xf1,0x47,0x14,0x0f,0xf3,0x6b,0xda,0x75,0x58,0x90,0xb0,0x31,0x1d,0x27,0xf5,0x1a,0x4e,0x52,0x25,0xa1,0x91,0xc8,0x35,0x7e,0xf1,0x76,0x9c,0x5e,0x57,0x53,0x81,0x6b,0xb7,0x3e,0x72,0x9b,0x0d,0x6f,0x40,0x83,0xfa,0x38,0xe4,0xa7,0x3f,0x1b,0xbb,0x76,0x0b,0x9b,0x93,0x92,0x7f,0xf9,0xc1,0xb8,0x08,0x6e,0xab,0x44,0xd4,0xcb,0x71,0x67,0xbe,0x17,0x80,0xbb,0x99,0x63,0x64,0xe5,0x22,0x55,0xa9,0x72,0xb7,0x1e,0xd6,0x6d,0x7b},
+    {0x92,0x3d,0xf3,0x50,0xe8,0xc1,0xad,0xb7,0xcf,0xd5,0x8c,0x60,0x4f,0xfa,0x98,0x79,0xdb,0x5b,0xfc,0x8d,0xbd,0x2d,0x96,0xad,0x4f,0x2f,0x1d,0xaf,0xce,0x9b,0x3e,0x70,0xc7,0xd2,0x01,0xab,0xf9,0xab,0x30,0x57,0x18,0x3b,0x14,0x40,0xdc,0x76,0xfb,0x16,0x81,0xb2,0xcb,0xa0,0x65,0xbe,0x6c,0x86,0xfe,0x6a,0xff,0x9b,0x65,0x9b,0xfa,0x53,0x55,0x54,0x88,0x94,0xe9,0xc8,0x14,0x6c,0xe5,0xd4,0xae,0x65,0x66,0x5d,0x3a,0x84,0xf1,0x5a,0xd6,0xbc,0x3e,0xb7,0x1b,0x18,0x50,0x1f,0xc6,0xc4,0xe5,0x93,0x8d,0x39},
+    {0xf3,0x48,0xe2,0x33,0x67,0xd1,0x4b,0x1c,0x5f,0x0a,0xbf,0x15,0x87,0x12,0x9e,0xbd,0x76,0x03,0x0b,0xa1,0xf0,0x8c,0x3f,0xd4,0x13,0x1b,0x19,0xdf,0x5d,0x9b,0xb0,0x53,0xf2,0xe3,0xe7,0xd2,0x60,0x7c,0x87,0xc3,0xb1,0x8b,0x82,0x30,0xa0,0xaa,0x34,0x3b,0x38,0xf1,0x9e,0x73,0xe7,0x26,0x3e,0x28,0x77,0x05,0xc3,0x02,0x90,0x9c,0x9c,0x69,0xcc,0xf1,0x46,0x59,0x23,0xa7,0x06,0xf3,0x7d,0xd9,0xe5,0xcc,0xb5,0x18,0x17,0x92,0x75,0xe9,0xb4,0x81,0x47,0xd2,0xcd,0x28,0x07,0xd9,0xcd,0x6f,0x0c,0xf3,0xca,0x51},
+    {0x0a,0xe0,0x74,0x76,0x42,0xa7,0x0b,0xa6,0xf3,0x7b,0x7a,0xa1,0x70,0x85,0x0e,0x63,0xcc,0x24,0x33,0xcf,0x3d,0x56,0x58,0x37,0xaa,0xfd,0x83,0x23,0x29,0xaa,0x04,0x55,0xc7,0x54,0xac,0x18,0x9a,0xf9,0x7a,0x73,0x0f,0xb3,0x1c,0xc5,0xdc,0x78,0x33,0x90,0xc7,0x0c,0xe1,0x4c,0x33,0xbc,0x89,0x2b,0x9a,0xe9,0xf8,0x89,0xc1,0x29,0xae,0x12,0xcf,0x01,0x0d,0x1f,0xcb,0xc0,0x9e,0xa9,0xae,0xf7,0x34,0x3a,0xcc,0xef,0xd1,0x0d,0x22,0x4e,0x9c,0xd0,0x21,0x75,0xca,0x55,0xea,0xa5,0xeb,0x58,0xe9,0x4f,0xd1,0x5f},
+    {0x2c,0xab,0x45,0x28,0xdf,0x2d,0xdc,0xb5,0x93,0xe9,0x7f,0x0a,0xb1,0x91,0x94,0x06,0x46,0xe3,0x02,0x40,0xd6,0xf3,0xaa,0x4d,0xd1,0x74,0x64,0x58,0x6e,0xf2,0x3f,0x09,0x8e,0xcb,0x93,0xbf,0x5e,0xfe,0x42,0x3c,0x5f,0x56,0xd4,0x36,0x51,0xa8,0xdf,0xbe,0xe8,0x20,0x42,0x88,0x9e,0x85,0xf0,0xe0,0x28,0xd1,0x25,0x07,0x96,0x3f,0xd7,0x7d,0x29,0x98,0x05,0x68,0xfe,0x24,0x0d,0xb1,0xe5,0x23,0xaf,0xdb,0x72,0x06,0x73,0x75,0x29,0xac,0x57,0xb4,0x3a,0x25,0x67,0x13,0xa4,0x70,0xb4,0x86,0xbc,0xbc,0x59,0x2f},
+    {0x5f,0x13,0x17,0x99,0x42,0x7d,0x84,0x83,0xd7,0x03,0x7d,0x56,0x1f,0x91,0x1b,0xad,0xd1,0xaa,0x77,0xbe,0xd9,0x48,0x77,0x7e,0x4a,0xaf,0x51,0x2e,0x2e,0xb4,0x58,0x54,0x01,0xc3,0x91,0xb6,0x60,0xd5,0x41,0x70,0x1e,0xe7,0xd7,0xad,0x3f,0x1b,0x20,0x85,0x85,0x55,0x33,0x11,0x63,0xe1,0xc2,0x16,0xb1,0x28,0x08,0x01,0x3d,0x5e,0xa5,0x2a,0x4f,0x44,0x07,0x0c,0xe6,0x92,0x51,0xed,0x10,0x1d,0x42,0x74,0x2d,0x4e,0xc5,0x42,0x64,0xc8,0xb5,0xfd,0x82,0x4c,0x2b,0x35,0x64,0x86,0x76,0x8a,0x4a,0x00,0xe9,0x13},
+    {0xdb,0xce,0x2f,0x83,0x45,0x88,0x9d,0x73,0x63,0xf8,0x6b,0xae,0xc9,0xd6,0x38,0xfa,0xf7,0xfe,0x4f,0xb7,0xca,0x0d,0xbc,0x32,0x5e,0xe4,0xbc,0x14,0x88,0x7e,0x93,0x73,0x7f,0x87,0x3b,0x19,0xc9,0x00,0x2e,0xbb,0x6b,0x50,0xdc,0xe0,0x90,0xa8,0xe3,0xec,0x9f,0x64,0xde,0x36,0xc0,0xb7,0xf3,0xec,0x1a,0x9e,0xde,0x98,0x08,0x04,0x46,0x5f,0x8d,0xf4,0x7b,0x29,0x16,0x71,0x03,0xb9,0x34,0x68,0xf0,0xd4,0x22,0x3b,0xd1,0xa9,0xc6,0xbd,0x96,0x46,0x57,0x15,0x97,0xe1,0x35,0xe8,0xd5,0x91,0xe8,0xa4,0xf8,0x2c},
+    {0x67,0x0f,0x11,0x07,0x87,0xfd,0x93,0x6d,0x49,0xb5,0x38,0x7c,0xd3,0x09,0x4c,0xdd,0x86,0x6a,0x73,0xc2,0x4c,0x6a,0xb1,0x7c,0x09,0x2a,0x25,0x58,0x6e,0xbd,0x49,0x20,0xa2,0x6b,0xd0,0x17,0x7e,0x48,0xb5,0x2c,0x6b,0x19,0x50,0x39,0x1c,0x38,0xd2,0x24,0x30,0x8a,0x97,0x85,0x81,0x9c,0x65,0xd7,0xf6,0xa4,0xd6,0x91,0x28,0x7f,0x6f,0x7a,0x49,0xef,0x9a,0x6a,0x8d,0xfd,0x09,0x7d,0x0b,0xb9,0x3d,0x5b,0xbe,0x60,0xee,0xf0,0xd4,0xbf,0x9e,0x51,0x2c,0xb5,0x21,0x4c,0x1d,0x94,0x45,0xc5,0xdf,0xaa,0x11,0x60},
+    {0x3c,0xf8,0x95,0xcf,0x6d,0x92,0x67,0x5f,0x71,0x90,0x28,0x71,0x61,0x85,0x7e,0x7c,0x5b,0x7a,0x8f,0x99,0xf3,0xe7,0xa1,0xd6,0xe0,0xf9,0x62,0x0b,0x1b,0xcc,0xc5,0x6f,0x90,0xf8,0xcb,0x02,0xc8,0xd0,0xde,0x63,0xaa,0x6a,0xff,0x0d,0xca,0x98,0xd0,0xfb,0x99,0xed,0xb6,0xb9,0xfd,0x0a,0x4d,0x62,0x1e,0x0b,0x34,0x79,0xb7,0x18,0xce,0x69,0xcb,0x79,0x98,0xb2,0x28,0x55,0xef,0xd1,0x92,0x90,0x7e,0xd4,0x3c,0xae,0x1a,0xdd,0x52,0x23,0x9f,0x18,0x42,0x04,0x7e,0x12,0xf1,0x01,0x71,0xe5,0x3a,0x6b,0x59,0x15},
+    {0xa2,0x79,0x91,0x3f,0xd2,0x39,0x27,0x46,0xcf,0xdd,0xd6,0x97,0x31,0x12,0x83,0xff,0x8a,0x14,0xf2,0x53,0xb5,0xde,0x07,0x13,0xda,0x4d,0x5f,0x7b,0x68,0x37,0x22,0x0d,0xca,0x24,0x51,0x7e,0x16,0x31,0xff,0x09,0xdf,0x45,0xc7,0xd9,0x8b,0x15,0xe4,0x0b,0xe5,0x56,0xf5,0x7e,0x22,0x7d,0x2b,0x29,0x38,0xd1,0xb6,0xaf,0x41,0xe2,0xa4,0x3a,0xf5,0x05,0x33,0x2a,0xbf,0x38,0xc1,0x2c,0xc3,0x26,0xe9,0xa2,0x8f,0x3f,0x58,0x48,0xeb,0xd2,0x49,0x55,0xa2,0xb1,0x3a,0x08,0x6c,0xa3,0x87,0x46,0x6e,0xaa,0xfc,0x32},
+    {0xf5,0x9a,0x7d,0xc5,0x8d,0x6e,0xc5,0x7b,0xf2,0xbd,0xf0,0x9d,0xed,0xd2,0x0b,0x3e,0xa3,0xe4,0xef,0x22,0xde,0x14,0xc0,0xaa,0x5c,0x6a,0xbd,0xfe,0xce,0xe9,0x27,0x46,0xdf,0xcc,0x87,0x27,0x73,0xa4,0x07,0x32,0xf8,0xe3,0x13,0xf2,0x08,0x19,0xe3,0x17,0x4e,0x96,0x0d,0xf6,0xd7,0xec,0xb2,0xd5,0xe9,0x0b,0x60,0xc2,0x36,0x63,0x6f,0x74,0x1c,0x97,0x6c,0xab,0x45,0xf3,0x4a,0x3f,0x1f,0x73,0x43,0x99,0x72,0xeb,0x88,0xe2,0x6d,0x18,0x44,0x03,0x8a,0x6a,0x59,0x33,0x93,0x62,0xd6,0x7e,0x00,0x17,0x49,0x7b},
+    {0x64,0xb0,0x84,0xab,0x5c,0xfb,0x85,0x2d,0x14,0xbc,0xf3,0x89,0xd2,0x10,0x78,0x49,0x0c,0xce,0x15,0x7b,0x44,0xdc,0x6a,0x47,0x7b,0xfd,0x44,0xf8,0x76,0xa3,0x2b,0x12,0xdd,0xa2,0x53,0xdd,0x28,0x1b,0x34,0x54,0x3f,0xfc,0x42,0xdf,0x5b,0x90,0x17,0xaa,0xf4,0xf8,0xd2,0x4d,0xd9,0x92,0xf5,0x0f,0x7d,0xd3,0x8c,0xe0,0x0f,0x62,0x03,0x1d,0x54,0xe5,0xb4,0xa2,0xcd,0x32,0x02,0xc2,0x7f,0x18,0x5d,0x11,0x42,0xfd,0xd0,0x9e,0xd9,0x79,0xd4,0x7d,0xbe,0xb4,0xab,0x2e,0x4c,0xec,0x68,0x2b,0xf5,0x0b,0xc7,0x02},
+    {0xbb,0x2f,0x0b,0x5d,0x4b,0xec,0x87,0xa2,0xca,0x82,0x48,0x07,0x90,0x57,0x5c,0x41,0x5c,0x81,0xd0,0xc1,0x1e,0xa6,0x44,0xe0,0xe0,0xf5,0x9e,0x40,0x0a,0x4f,0x33,0x26,0xe1,0x72,0x8d,0x45,0xbf,0x32,0xe5,0xac,0xb5,0x3c,0xb7,0x7c,0xe0,0x68,0xe7,0x5b,0xe7,0xbd,0x8b,0xee,0x94,0x7d,0xcf,0x56,0x03,0x3a,0xb4,0xfe,0xe3,0x97,0x06,0x6b,0xc0,0xa3,0x62,0xdf,0x4a,0xf0,0xc8,0xb6,0x5d,0xa4,0x6d,0x07,0xef,0x00,0xf0,0x3e,0xa9,0xd2,0xf0,0x49,0x58,0xb9,0x9c,0x9c,0xae,0x2f,0x1b,0x44,0x43,0x7f,0xc3,0x1c},
+    {0x4f,0x32,0xc7,0x5c,0x5a,0x56,0x8f,0x50,0x22,0xa9,0x06,0xe5,0xc0,0xc4,0x61,0xd0,0x19,0xac,0x45,0x5c,0xdb,0xab,0x18,0xfb,0x4a,0x31,0x80,0x03,0xc1,0x09,0x68,0x6c,0xb9,0xae,0xce,0xc9,0xf1,0x56,0x66,0xd7,0x6a,0x65,0xe5,0x18,0xf8,0x15,0x5b,0x1c,0x34,0x23,0x4c,0x84,0x32,0x28,0xe7,0x26,0x38,0x68,0x19,0x2f,0x77,0x6f,0x34,0x3a,0xc8,0x6a,0xda,0xe2,0x12,0x51,0xd5,0xd2,0xed,0x51,0xe8,0xb1,0x31,0x03,0xbd,0xe9,0x62,0x72,0xc6,0x8e,0xdd,0x46,0x07,0x96,0xd0,0xc5,0xf7,0x6e,0x9f,0x1b,0x91,0x05},
+    {0xbb,0x0e,0xdf,0xf5,0x83,0x99,0x33,0xc1,0xac,0x4c,0x2c,0x51,0x8f,0x75,0xf3,0xc0,0xe1,0x98,0xb3,0x0b,0x0a,0x13,0xf1,0x2c,0x62,0x0c,0x27,0xaa,0xf9,0xec,0x3c,0x6b,0xef,0xea,0x2e,0x51,0xf3,0xac,0x49,0x53,0x49,0xcb,0xc1,0x1c,0xd3,0x41,0xc1,0x20,0x8d,0x68,0x9a,0xa9,0x07,0x0c,0x18,0x24,0x17,0x2d,0x4b,0xc6,0xd1,0xf9,0x5e,0x55,0x08,0xbd,0x73,0x3b,0xba,0x70,0xa7,0x36,0x0c,0xbf,0xaf,0xa3,0x08,0xef,0x4a,0x62,0xf2,0x46,0x09,0xb4,0x98,0xff,0x37,0x57,0x9d,0x74,0x81,0x33,0xe1,0x4d,0x5f,0x67},
+    {0xfc,0x82,0x17,0x6b,0x03,0x52,0x2c,0x0e,0xb4,0x83,0xad,0x6c,0x81,0x6c,0x81,0x64,0x3e,0x07,0x64,0x69,0xd9,0xbd,0xdc,0xd0,0x20,0xc5,0x64,0x01,0xf7,0x9d,0xd9,0x13,0x1d,0xb3,0xda,0x3b,0xd9,0xf6,0x2f,0xa1,0xfe,0x2d,0x65,0x9d,0x0f,0xd8,0x25,0x07,0x87,0x94,0xbe,0x9a,0xf3,0x4f,0x9c,0x01,0x43,0x3c,0xcd,0x82,0xb8,0x50,0xf4,0x60,0xca,0xc0,0xe5,0x21,0xc3,0x5e,0x4b,0x01,0xa2,0xbf,0x19,0xd7,0xc9,0x69,0xcb,0x4f,0xa0,0x23,0x00,0x75,0x18,0x1c,0x5f,0x4e,0x80,0xac,0xed,0x55,0x9e,0xde,0x06,0x1c},
+    {0xe2,0xc4,0x3e,0xa3,0xd6,0x7a,0x0f,0x99,0x8e,0xe0,0x2e,0xbe,0x38,0xf9,0x08,0x66,0x15,0x45,0x28,0x63,0xc5,0x43,0xa1,0x9c,0x0d,0xb6,0x2d,0xec,0x1f,0x8a,0xf3,0x4c,0xaa,0x69,0x6d,0xff,0x40,0x2b,0xd5,0xff,0xbb,0x49,0x40,0xdc,0x18,0x0b,0x53,0x34,0x97,0x98,0x4d,0xa3,0x2f,0x5c,0x4a,0x5e,0x2d,0xba,0x32,0x7d,0x8e,0x6f,0x09,0x78,0xe7,0x5c,0xfa,0x0d,0x65,0xaa,0xaa,0xa0,0x8c,0x47,0xb5,0x48,0x2a,0x9e,0xc4,0xf9,0x5b,0x72,0x03,0x70,0x7d,0xcc,0x09,0x4f,0xbe,0x1a,0x09,0x26,0x3a,0xad,0x3c,0x37},
+    {0x7c,0xf5,0xc9,0x82,0x4d,0x63,0x94,0xb2,0x36,0x45,0x93,0x24,0xe1,0xfd,0xcb,0x1f,0x5a,0xdb,0x8c,0x41,0xb3,0x4d,0x9c,0x9e,0xfc,0x19,0x44,0x45,0xd9,0xf3,0x40,0x00,0xad,0xbb,0xdd,0x89,0xfb,0xa8,0xbe,0xf1,0xcb,0xae,0xae,0x61,0xbc,0x2c,0xcb,0x3b,0x9d,0x8d,0x9b,0x1f,0xbb,0xa7,0x58,0x8f,0x86,0xa6,0x12,0x51,0xda,0x7e,0x54,0x21,0xd3,0x86,0x59,0xfd,0x39,0xe9,0xfd,0xde,0x0c,0x38,0x0a,0x51,0x89,0x2c,0x27,0xf4,0xb9,0x19,0x31,0xbb,0x07,0xa4,0x2b,0xb7,0xf4,0x4d,0x25,0x4a,0x33,0x0a,0x55,0x63},
+    {0x37,0xcf,0x69,0xb5,0xed,0xd6,0x07,0x65,0xe1,0x2e,0xa5,0x0c,0xb0,0x29,0x84,0x17,0x5d,0xd6,0x6b,0xeb,0x90,0x00,0x7c,0xea,0x51,0x8f,0xf7,0xda,0xc7,0x62,0xea,0x3e,0x49,0x7b,0x54,0x72,0x45,0x58,0xba,0x9b,0xe0,0x08,0xc4,0xe2,0xfa,0xc6,0x05,0xf3,0x8d,0xf1,0x34,0xc7,0x69,0xfa,0xe8,0x60,0x7a,0x76,0x7d,0xaa,0xaf,0x2b,0xa9,0x39,0x4e,0x27,0x93,0xe6,0x13,0xc7,0x24,0x9d,0x75,0xd3,0xdb,0x68,0x77,0x85,0x63,0x5f,0x9a,0xb3,0x8a,0xeb,0x60,0x55,0x52,0x70,0xcd,0xc4,0xc9,0x65,0x06,0x6a,0x43,0x68},
+    {0x27,0x3f,0x2f,0x20,0xe8,0x35,0x02,0xbc,0xb0,0x75,0xf9,0x64,0xe2,0x00,0x5c,0xc7,0x16,0x24,0x8c,0xa3,0xd5,0xe9,0xa4,0x91,0xf9,0x89,0xb7,0x8a,0xf6,0xe7,0xb6,0x17,0x7c,0x10,0x20,0xe8,0x17,0xd3,0x56,0x1e,0x65,0xe9,0x0a,0x84,0x44,0x68,0x26,0xc5,0x7a,0xfc,0x0f,0x32,0xc6,0xa1,0xe0,0xc1,0x72,0x14,0x61,0x91,0x9c,0x66,0x73,0x53,0x57,0x52,0x0e,0x9a,0xab,0x14,0x28,0x5d,0xfc,0xb3,0xca,0xc9,0x84,0x20,0x8f,0x90,0xca,0x1e,0x2d,0x5b,0x88,0xf5,0xca,0xaf,0x11,0x7d,0xf8,0x78,0xa6,0xb5,0xb4,0x1c},
+    {0x6c,0xfc,0x4a,0x39,0x6b,0xc0,0x64,0xb6,0xb1,0x5f,0xda,0x98,0x24,0xde,0x88,0x0c,0x34,0xd8,0xca,0x4b,0x16,0x03,0x8d,0x4f,0xa2,0x34,0x74,0xde,0x78,0xca,0x0b,0x33,0xe7,0x07,0xa0,0xa2,0x62,0xaa,0x74,0x6b,0xb1,0xc7,0x71,0xf0,0xb0,0xe0,0x11,0xf3,0x23,0xe2,0x0b,0x00,0x38,0xe4,0x07,0x57,0xac,0x6e,0xef,0x82,0x2d,0xfd,0xc0,0x2d,0x4e,0x74,0x19,0x11,0x84,0xff,0x2e,0x98,0x24,0x47,0x07,0x2b,0x96,0x5e,0x69,0xf9,0xfb,0x53,0xc9,0xbf,0x4f,0xc1,0x8a,0xc5,0xf5,0x1c,0x9f,0x36,0x1b,0xbe,0x31,0x3c},
+    {0xee,0x8a,0x94,0x08,0x4d,0x86,0xf4,0xb0,0x6f,0x1c,0xba,0x91,0xee,0x19,0xdc,0x07,0x58,0xa1,0xac,0xa6,0xae,0xcd,0x75,0x79,0xbb,0xd4,0x62,0x42,0x13,0x61,0x0b,0x33,0x72,0x42,0xcb,0xf9,0x93,0xbc,0x68,0xc1,0x98,0xdb,0xce,0xc7,0x1f,0x71,0xb8,0xae,0x7a,0x8d,0xac,0x34,0xaa,0x52,0x0e,0x7f,0xbb,0x55,0x7d,0x7e,0x09,0xc1,0xce,0x41,0x8a,0x80,0x6d,0xa2,0xd7,0x19,0x96,0xf7,0x6d,0x15,0x9e,0x1d,0x9e,0xd4,0x1f,0xbb,0x27,0xdf,0xa1,0xdb,0x6c,0xc3,0xd7,0x73,0x7d,0x77,0x28,0x1f,0xd9,0x4c,0xb4,0x26},
+    {0x75,0x74,0x38,0x8f,0x47,0x48,0xf0,0x51,0x3c,0xcb,0xbe,0x9c,0xf4,0xbc,0x5d,0xb2,0x55,0x20,0x9f,0xd9,0x44,0x12,0xab,0x9a,0xd6,0xa5,0x10,0x1c,0x6c,0x9e,0x70,0x2c,0x83,0x03,0x73,0x62,0x93,0xf2,0xb7,0xe1,0x2c,0x8a,0xca,0xeb,0xff,0x79,0x52,0x4b,0x14,0x13,0xd4,0xbf,0x8a,0x77,0xfc,0xda,0x0f,0x61,0x72,0x9c,0x14,0x10,0xeb,0x7d,0x7a,0xee,0x66,0x87,0x6a,0xaf,0x62,0xcb,0x0e,0xcd,0x53,0x55,0x04,0xec,0xcb,0x66,0xb5,0xe4,0x0b,0x0f,0x38,0x01,0x80,0x58,0xea,0xe2,0x2c,0xf6,0x9f,0x8e,0xe6,0x08},
+    {0xad,0x30,0xc1,0x4b,0x0a,0x50,0xad,0x34,0x9c,0xd4,0x0b,0x3d,0x49,0xdb,0x38,0x8d,0xbe,0x89,0x0a,0x50,0x98,0x3d,0x5c,0xa2,0x09,0x3b,0xba,0xee,0x87,0x3f,0x1f,0x2f,0xf9,0xf2,0xb8,0x0a,0xd5,0x09,0x2d,0x2f,0xdf,0x23,0x59,0xc5,0x8d,0x21,0xb9,0xac,0xb9,0x6c,0x76,0x73,0x26,0x34,0x8f,0x4a,0xf5,0x19,0xf7,0x38,0xd7,0x3b,0xb1,0x4c,0x4a,0xb6,0x15,0xe5,0x75,0x8c,0x84,0xf7,0x38,0x90,0x4a,0xdb,0xba,0x01,0x95,0xa5,0x50,0x1b,0x75,0x3f,0x3f,0x31,0x0d,0xc2,0xe8,0x2e,0xae,0xc0,0x53,0xe3,0xa1,0x19},
+    {0xc3,0x05,0xfa,0xba,0x60,0x75,0x1c,0x7d,0x61,0x5e,0xe5,0xc6,0xa0,0xa0,0xe1,0xb3,0x73,0x64,0xd6,0xc0,0x18,0x97,0x52,0xe3,0x86,0x34,0x0c,0xc2,0x11,0x6b,0x54,0x41,0xbd,0xbd,0x96,0xd5,0xcd,0x72,0x21,0xb4,0x40,0xfc,0xee,0x98,0x43,0x45,0xe0,0x93,0xb5,0x09,0x41,0xb4,0x47,0x53,0xb1,0x9f,0x34,0xae,0x66,0x02,0x99,0xd3,0x6b,0x73,0xb4,0xb3,0x34,0x93,0x50,0x2d,0x53,0x85,0x73,0x65,0x81,0x60,0x4b,0x11,0xfd,0x46,0x75,0x83,0x5c,0x42,0x30,0x5f,0x5f,0xcc,0x5c,0xab,0x7f,0xb8,0xa2,0x95,0x22,0x41},
+    {0xe9,0xd6,0x7e,0xf5,0x88,0x9b,0xc9,0x19,0x25,0xc8,0xf8,0x6d,0x26,0xcb,0x93,0x53,0x73,0xd2,0x0a,0xb3,0x13,0x32,0xee,0x5c,0x34,0x2e,0x2d,0xb5,0xeb,0x53,0xe1,0x14,0xc6,0xea,0x93,0xe2,0x61,0x52,0x65,0x2e,0xdb,0xac,0x33,0x21,0x03,0x92,0x5a,0x84,0x6b,0x99,0x00,0x79,0xcb,0x75,0x09,0x46,0x80,0xdd,0x5a,0x19,0x8d,0xbb,0x60,0x07,0x8a,0x81,0xe6,0xcd,0x17,0x1a,0x3e,0x41,0x84,0xa0,0x69,0xed,0xa9,0x6d,0x15,0x57,0xb1,0xcc,0xca,0x46,0x8f,0x26,0xbf,0x2c,0xf2,0xc5,0x3a,0xc3,0x9b,0xbe,0x34,0x6b},
+    {0xb2,0xc0,0x78,0x3a,0x64,0x2f,0xdf,0xf3,0x7c,0x02,0x2e,0xf2,0x1e,0x97,0x3e,0x4c,0xa3,0xb5,0xc1,0x49,0x5e,0x1c,0x7d,0xec,0x2d,0xdd,0x22,0x09,0x8f,0xc1,0x12,0x20,0xd3,0xf2,0x71,0x65,0x65,0x69,0xfc,0x11,0x7a,0x73,0x0e,0x53,0x45,0xe8,0xc9,0xc6,0x35,0x50,0xfe,0xd4,0xa2,0xe7,0x3a,0xe3,0x0b,0xd3,0x6d,0x2e,0xb6,0xc7,0xb9,0x01,0x29,0x9d,0xc8,0x5a,0xe5,0x55,0x0b,0x88,0x63,0xa7,0xa0,0x45,0x1f,0x24,0x83,0x14,0x1f,0x6c,0xe7,0xc2,0xdf,0xef,0x36,0x3d,0xe8,0xad,0x4b,0x4e,0x78,0x5b,0xaf,0x08},
+    {0x33,0x25,0x1f,0x88,0xdc,0x99,0x34,0x28,0xb6,0x23,0x93,0x77,0xda,0x25,0x05,0x9d,0xf4,0x41,0x34,0x67,0xfb,0xdd,0x7a,0x89,0x8d,0x16,0x3a,0x16,0x71,0x9d,0xb7,0x32,0x4b,0x2c,0xcc,0x89,0xd2,0x14,0x73,0xe2,0x8d,0x17,0x87,0xa2,0x11,0xbd,0xe4,0x4b,0xce,0x64,0x33,0xfa,0xd6,0x28,0xd5,0x18,0x6e,0x82,0xd9,0xaf,0xd5,0xc1,0x23,0x64,0x6a,0xb3,0xfc,0xed,0xd9,0xf8,0x85,0xcc,0xf9,0xe5,0x46,0x37,0x8f,0xc2,0xbc,0x22,0xcd,0xd3,0xe5,0xf9,0x38,0xe3,0x9d,0xe4,0xcc,0x2d,0x3e,0xc1,0xfb,0x5e,0x0a,0x48},
+    {0x71,0x20,0x62,0x01,0x0b,0xe7,0x51,0x0b,0xc5,0xaf,0x1d,0x8b,0xcf,0x05,0xb5,0x06,0xcd,0xab,0x5a,0xef,0x61,0xb0,0x6b,0x2c,0x31,0xbf,0xb7,0x0c,0x60,0x27,0xaa,0x47,0x1f,0x22,0xce,0x42,0xe4,0x4c,0x61,0xb6,0x28,0x39,0x05,0x4c,0xcc,0x9d,0x19,0x6e,0x03,0xbe,0x1c,0xdc,0xa4,0xb4,0x3f,0x66,0x06,0x8e,0x1c,0x69,0x47,0x1d,0xb3,0x24,0xc3,0xf8,0x15,0xc0,0xed,0x1e,0x54,0x2a,0x7c,0x3f,0x69,0x7c,0x7e,0xfe,0xa4,0x11,0xd6,0x78,0xa2,0x4e,0x13,0x66,0xaf,0xf0,0x94,0xa0,0xdd,0x14,0x5d,0x58,0x5b,0x54},
+    {0x0f,0x3a,0xd4,0xa0,0x5e,0x27,0xbf,0x67,0xbe,0xee,0x9b,0x08,0x34,0x8e,0xe6,0xad,0x2e,0xe7,0x79,0xd4,0x4c,0x13,0x89,0x42,0x54,0x54,0xba,0x32,0xc3,0xf9,0x62,0x0f,0xe1,0x21,0xb3,0xe3,0xd0,0xe4,0x04,0x62,0x95,0x1e,0xff,0x28,0x7a,0x63,0xaa,0x3b,0x9e,0xbd,0x99,0x5b,0xfd,0xcf,0x0c,0x0b,0x71,0xd0,0xc8,0x64,0x3e,0xdc,0x22,0x4d,0x39,0x5f,0x3b,0xd6,0x89,0x65,0xb4,0xfc,0x61,0xcf,0xcb,0x57,0x3f,0x6a,0xae,0x5c,0x05,0xfa,0x3a,0x95,0xd2,0xc2,0xba,0xfe,0x36,0x14,0x37,0x36,0x1a,0xa0,0x0f,0x1c},
+    {0xff,0x3d,0x94,0x22,0xb6,0x04,0xc6,0xd2,0xa0,0xb3,0xcf,0x44,0xce,0xbe,0x8c,0xbc,0x78,0x86,0x80,0x97,0xf3,0x4f,0x25,0x5d,0xbf,0xa6,0x1c,0x3b,0x4f,0x61,0xa3,0x0f,0x50,0x6a,0x93,0x8c,0x0e,0x2b,0x08,0x69,0xb6,0xc5,0xda,0xc1,0x35,0xa0,0xc9,0xf9,0x34,0xb6,0xdf,0xc4,0x54,0x3e,0xb7,0x6f,0x40,0xc1,0x2b,0x1d,0x9b,0x41,0x05,0x40,0xf0,0x82,0xbe,0xb9,0xbd,0xfe,0x03,0xa0,0x90,0xac,0x44,0x3a,0xaf,0xc1,0x89,0x20,0x8e,0xfa,0x54,0x19,0x91,0x9f,0x49,0xf8,0x42,0xab,0x40,0xef,0x8a,0x21,0xba,0x1f},
+    {0x3e,0xf5,0xc8,0xfa,0x48,0x94,0x54,0xab,0x41,0x37,0xa6,0x7b,0x9a,0xe8,0xf6,0x81,0x01,0x5e,0x2b,0x6c,0x7d,0x6c,0xfd,0x74,0x42,0x6e,0xc8,0xa8,0xca,0x3a,0x2e,0x39,0x94,0x01,0x7b,0x3e,0x04,0x57,0x3e,0x4f,0x7f,0xaf,0xda,0x08,0xee,0x3e,0x1d,0xa8,0xf1,0xde,0xdc,0x99,0xab,0xc6,0x39,0xc8,0xd5,0x61,0x77,0xff,0x13,0x5d,0x53,0x6c,0xaf,0x35,0x8a,0x3e,0xe9,0x34,0xbd,0x4c,0x16,0xe8,0x87,0x58,0x44,0x81,0x07,0x2e,0xab,0xb0,0x9a,0xf2,0x76,0x9c,0x31,0x19,0x3b,0xc1,0x0a,0xd5,0xe4,0x7f,0xe1,0x25},
+    {0x76,0xf6,0x04,0x1e,0xd7,0x9b,0x28,0x0a,0x95,0x0f,0x42,0xd6,0x52,0x1c,0x8e,0x20,0xab,0x1f,0x69,0x34,0xb0,0xd8,0x86,0x51,0x51,0xb3,0x9f,0x2a,0x44,0x51,0x57,0x25,0xa7,0x21,0xf1,0x76,0xf5,0x7f,0x5f,0x91,0xe3,0x87,0xcd,0x2f,0x27,0x32,0x4a,0xc3,0x26,0xe5,0x1b,0x4d,0xde,0x2f,0xba,0xcc,0x9b,0x89,0x69,0x89,0x8f,0x82,0xba,0x6b,0x01,0x39,0xfe,0x90,0x66,0xbc,0xd1,0xe2,0xd5,0x7a,0x99,0xa0,0x18,0x4a,0xb5,0x4c,0xd4,0x60,0x84,0xaf,0x14,0x69,0x1d,0x97,0xe4,0x7b,0x6b,0x7f,0x4f,0x50,0x9d,0x55},
+    {0xd5,0x54,0xeb,0xb3,0x78,0x83,0x73,0xa7,0x7c,0x3c,0x55,0xa5,0x66,0xd3,0x69,0x1d,0xba,0x00,0x28,0xf9,0x62,0xcf,0x26,0x0a,0x17,0x32,0x7e,0x80,0xd5,0x12,0xab,0x01,0xfd,0x66,0xd2,0xf6,0xe7,0x91,0x48,0x9c,0x1b,0x78,0x07,0x03,0x9b,0xa1,0x44,0x07,0x3b,0xe2,0x61,0x60,0x1d,0x8f,0x38,0x88,0x0e,0xd5,0x4b,0x35,0xa3,0xa6,0x3e,0x12,0x96,0x2d,0xe3,0x41,0x90,0x18,0x8d,0x11,0x48,0x58,0x31,0xd8,0xc2,0xe3,0xed,0xb9,0xd9,0x45,0x32,0xd8,0x71,0x42,0xab,0x1e,0x54,0xa1,0x18,0xc9,0xe2,0x61,0x39,0x4a},
+    {0xa0,0xbb,0xe6,0xf8,0xe0,0x3b,0xdc,0x71,0x0a,0xe3,0xff,0x7e,0x34,0xf8,0xce,0xd6,0x6a,0x47,0x3a,0xe1,0x5f,0x42,0x92,0xa9,0x63,0xb7,0x1d,0xfb,0xe3,0xbc,0xd6,0x2c,0x1e,0x3f,0x23,0xf3,0x44,0xd6,0x27,0x03,0x16,0xf0,0xfc,0x34,0x0e,0x26,0x9a,0x49,0x79,0xb9,0xda,0xf2,0x16,0xa7,0xb5,0x83,0x1f,0x11,0xd4,0x9b,0xad,0xee,0xac,0x68,0x10,0xc2,0xd7,0xf3,0x0e,0xc9,0xb4,0x38,0x0c,0x04,0xad,0xb7,0x24,0x6e,0x8e,0x30,0x23,0x3e,0xe7,0xb7,0xf1,0xd9,0x60,0x38,0x97,0xf5,0x08,0xb5,0xd5,0x60,0x57,0x59},
+    {0x97,0x63,0xaa,0x04,0xe1,0xbf,0x29,0x61,0xcb,0xfc,0xa7,0xa4,0x08,0x00,0x96,0x8f,0x58,0x94,0x90,0x7d,0x89,0xc0,0x8b,0x3f,0xa9,0x91,0xb2,0xdc,0x3e,0xa4,0x9f,0x70,0x90,0x27,0x02,0xfd,0xeb,0xcb,0x2a,0x88,0x60,0x57,0x11,0xc4,0x05,0x33,0xaf,0x89,0xf4,0x73,0x34,0x7d,0xe3,0x92,0xf4,0x65,0x2b,0x5a,0x51,0x54,0xdf,0xc5,0xb2,0x2c,0xca,0x2a,0xfd,0x63,0x8c,0x5d,0x0a,0xeb,0xff,0x4e,0x69,0x2e,0x66,0xc1,0x2b,0xd2,0x3a,0xb0,0xcb,0xf8,0x6e,0xf3,0x23,0x27,0x1f,0x13,0xc8,0xf0,0xec,0x29,0xf0,0x70},
+    {0x33,0x3e,0xed,0x2e,0xb3,0x07,0x13,0x46,0xe7,0x81,0x55,0xa4,0x33,0x2f,0x04,0xae,0x66,0x03,0x5f,0x19,0xd3,0x49,0x44,0xc9,0x58,0x48,0x31,0x6c,0x8a,0x5d,0x7d,0x0b,0xb9,0xb0,0x10,0x5e,0xaa,0xaf,0x6a,0x2a,0xa9,0x1a,0x04,0xef,0x70,0xa3,0xf0,0x78,0x1f,0xd6,0x3a,0xaa,0x77,0xfb,0x3e,0x77,0xe1,0xd9,0x4b,0xa7,0xa2,0xa5,0xec,0x44,0x43,0xd5,0x95,0x7b,0x32,0x48,0xd4,0x25,0x1d,0x0f,0x34,0xa3,0x00,0x83,0xd3,0x70,0x2b,0xc5,0xe1,0x60,0x1c,0x53,0x1c,0xde,0xe4,0xe9,0x7d,0x2c,0x51,0x24,0x22,0x27},
+    {0x2e,0x34,0xc5,0x49,0xaf,0x92,0xbc,0x1a,0xd0,0xfa,0xe6,0xb2,0x11,0xd8,0xee,0xff,0x29,0x4e,0xc8,0xfc,0x8d,0x8c,0xa2,0xef,0x43,0xc5,0x4c,0xa4,0x18,0xdf,0xb5,0x11,0xfc,0x75,0xa9,0x42,0x8a,0xbb,0x7b,0xbf,0x58,0xa3,0xad,0x96,0x77,0x39,0x5c,0x8c,0x48,0xaa,0xed,0xcd,0x6f,0xc7,0x7f,0xe2,0xa6,0x20,0xbc,0xf6,0xd7,0x5f,0x73,0x19,0x66,0x42,0xc8,0x42,0xd0,0x90,0xab,0xe3,0x7e,0x54,0x19,0x7f,0x0f,0x8e,0x84,0xeb,0xb9,0x97,0xa4,0x65,0xd0,0xa1,0x03,0x25,0x5f,0x89,0xdf,0x91,0x11,0x91,0xef,0x0f}
+};
+
+NAMESPACE_END  // Arch64
+NAMESPACE_END  // Donna
+NAMESPACE_END  // CryptoPP
+
+#endif  // CRYPTOPP_DOXYGEN_PROCESSING
+#endif  // CRYPTOPP_DONNA_64_H

+ 86 - 0
include/cryptlib/donna_sse.h

@@ -0,0 +1,86 @@
+// donna_sse.h - written and placed in public domain by Jeffrey Walton
+//               Crypto++ specific implementation wrapped around Andrew
+//               Moon's public domain curve25519-donna and ed25519-donna,
+//               https://github.com/floodyberry/curve25519-donna and
+//               https://github.com/floodyberry/ed25519-donna.
+
+// This source file multiplexes two different repos using namespaces. This
+// was a little easier from a project management standpoint. We only need
+// two files per architecture at the expense of namespaces and bloat.
+
+#ifndef CRYPTOPP_DONNA_SSE_H
+#define CRYPTOPP_DONNA_SSE_H
+#ifndef CRYPTOPP_DOXYGEN_PROCESSING
+
+#include "config.h"
+#include <emmintrin.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+NAMESPACE_BEGIN(Donna)
+NAMESPACE_BEGIN(ArchSSE)
+
+using CryptoPP::byte;
+using CryptoPP::word32;
+
+typedef __m128i xmmi;
+#define ALIGN(n) CRYPTOPP_ALIGN_DATA(n)
+
+typedef union packedelem8_t {
+    byte u[16];
+    xmmi v;
+} packedelem8;
+
+typedef union packedelem32_t {
+    word32 u[4];
+    xmmi v;
+} packedelem32;
+
+typedef union packedelem64_t {
+    word64 u[2];
+    xmmi v;
+} packedelem64;
+
+/* 10 elements + an extra 2 to fit in 3 xmm registers */
+typedef word32 bignum25519[12];
+typedef packedelem32 packed32bignum25519[5];
+typedef packedelem64 packed64bignum25519[10];
+
+const word32 reduce_mask_26 = (1 << 26) - 1;
+const word32 reduce_mask_25 = (1 << 25) - 1;
+
+const packedelem32 sse2_bot32bitmask = {{0xffffffff, 0x00000000, 0xffffffff, 0x00000000}};
+const packedelem32 sse2_top32bitmask = {{0x00000000, 0xffffffff, 0x00000000, 0xffffffff}};
+const packedelem32 sse2_top64bitmask = {{0x00000000, 0x00000000, 0xffffffff, 0xffffffff}};
+const packedelem32 sse2_bot64bitmask = {{0xffffffff, 0xffffffff, 0x00000000, 0x00000000}};
+
+/* reduction masks */
+const packedelem64 packedmask26 = {{0x03ffffff, 0x03ffffff}};
+const packedelem64 packedmask25 = {{0x01ffffff, 0x01ffffff}};
+const packedelem32 packedmask2625 = {{0x3ffffff,0,0x1ffffff,0}};
+const packedelem32 packedmask26262626 = {{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff}};
+const packedelem32 packedmask25252525 = {{0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff}};
+
+/* multipliers */
+const packedelem64 packednineteen = {{19, 19}};
+const packedelem64 packednineteenone = {{19, 1}};
+const packedelem64 packedthirtyeight = {{38, 38}};
+const packedelem64 packed3819 = {{19*2,19}};
+const packedelem64 packed9638 = {{19*4,19*2}};
+
+/* 121666,121665 */
+const packedelem64 packed121666121665 = {{121666, 121665}};
+
+/* 2*(2^255 - 19) = 0 mod p */
+const packedelem32 packed2p0 = {{0x7ffffda,0x3fffffe,0x7fffffe,0x3fffffe}};
+const packedelem32 packed2p1 = {{0x7fffffe,0x3fffffe,0x7fffffe,0x3fffffe}};
+const packedelem32 packed2p2 = {{0x7fffffe,0x3fffffe,0x0000000,0x0000000}};
+
+const packedelem32 packed32zeromodp0 = {{0x7ffffda,0x7ffffda,0x3fffffe,0x3fffffe}};
+const packedelem32 packed32zeromodp1 = {{0x7fffffe,0x7fffffe,0x3fffffe,0x3fffffe}};
+
+NAMESPACE_END  // ArchSSE
+NAMESPACE_END  // Donna
+NAMESPACE_END  // CryptoPP
+
+#endif  // CRYPTOPP_DOXYGEN_PROCESSING
+#endif  // CRYPTOPP_DONNA_SSE_H

+ 169 - 196
include/cryptlib/drbg.h

@@ -3,7 +3,7 @@
 /// \file drbg.h
 /// \brief Classes for NIST DRBGs from SP 800-90A
 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
-///   for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
+///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
 /// \since Crypto++ 6.0
 
 #ifndef CRYPTOPP_NIST_DRBG_H
@@ -18,8 +18,10 @@ NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief Interface for NIST DRBGs from SP 800-90A
 /// \details NIST_DRBG is the base class interface for NIST DRBGs from SP 800-90A Rev 1 (June 2015)
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
-///   for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
+///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
 /// \since Crypto++ 6.0
 class NIST_DRBG : public RandomNumberGenerator
 {
@@ -43,11 +45,11 @@ public:
     /// \brief Update RNG state with additional unpredictable values
     /// \param input the entropy to add to the generator
     /// \param length the size of the input buffer
-    /// \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy
+    /// \throw NIST_DRBG::Err if the generator is reseeded with insufficient entropy
     /// \details NIST instantiation and reseed requirements demand the generator is constructed
-    ///   with at least <tt>MINIMUM_ENTROPY</tt> entropy. The byte array for <tt>input</tt> must
-    ///   meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
-    ///   SP 800-90C</A> requirements.
+    ///  with at least <tt>MINIMUM_ENTROPY</tt> entropy. The byte array for <tt>input</tt> must
+    ///  meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
+    ///  SP 800-90C</A> requirements.
     virtual void IncorporateEntropy(const byte *input, size_t length)=0;
 
     /// \brief Update RNG state with additional unpredictable values
@@ -55,19 +57,19 @@ public:
     /// \param entropyLength the size of the input buffer
     /// \param additional additional input to add to the generator
     /// \param additionaLength the size of the additional input buffer
-    /// \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy
+    /// \throw NIST_DRBG::Err if the generator is reseeded with insufficient entropy
     /// \details IncorporateEntropy() is an overload provided to match NIST requirements. NIST
-    ///   instantiation and reseed requirements demand the generator is constructed with at least
-    ///   <tt>MINIMUM_ENTROPY</tt> entropy. The byte array for <tt>entropy</tt> must meet
-    ///   <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
+    ///  instantiation and reseed requirements demand the generator is constructed with at least
+    ///  <tt>MINIMUM_ENTROPY</tt> entropy. The byte array for <tt>entropy</tt> must meet
+    ///  <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
     ///!  SP 800-90C</A> requirements.
     virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
 
     /// \brief Generate random array of bytes
     /// \param output the byte buffer
     /// \param size the length of the buffer, in bytes
-    /// \throws NIST_DRBG::Err if a reseed is required
-    /// \throws NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
+    /// \throw NIST_DRBG::Err if a reseed is required
+    /// \throw NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
     virtual void GenerateBlock(byte *output, size_t size)=0;
 
     /// \brief Generate random array of bytes
@@ -75,65 +77,65 @@ public:
     /// \param additionaLength the size of the additional input buffer
     /// \param output the byte buffer
     /// \param size the length of the buffer, in bytes
-    /// \throws NIST_DRBG::Err if a reseed is required
-    /// \throws NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
+    /// \throw NIST_DRBG::Err if a reseed is required
+    /// \throw NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
     /// \details GenerateBlock() is an overload provided to match NIST requirements. The byte
-    ///   array for <tt>additional</tt> input is optional. If present the additional randomness
-    ///   is mixed before generating the output bytes.
+    ///  array for <tt>additional</tt> input is optional. If present the additional randomness
+    ///  is mixed before generating the output bytes.
     virtual void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)=0;
 
     /// \brief Provides the security strength
-    /// \returns The security strength of the generator, in bytes
+    /// \return The security strength of the generator, in bytes
     /// \details The equivalent class constant is <tt>SECURITY_STRENGTH</tt>
     virtual unsigned int SecurityStrength() const=0;
 
     /// \brief Provides the seed length
-    /// \returns The seed size of the generator, in bytes
+    /// \return The seed size of the generator, in bytes
     /// \details The equivalent class constant is <tt>SEED_LENGTH</tt>. The size is
-    ///   used to maintain internal state of <tt>V</tt> and <tt>C</tt>.
+    ///  used to maintain internal state of <tt>V</tt> and <tt>C</tt>.
     virtual unsigned int SeedLength() const=0;
 
     /// \brief Provides the minimum entropy size
-    /// \returns The minimum entropy size required by the generator, in bytes
+    /// \return The minimum entropy size required by the generator, in bytes
     /// \details The equivalent class constant is <tt>MINIMUM_ENTROPY</tt>. All NIST DRBGs must
-    ///   be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy. The bytes must
-    ///   meet <A HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
-    ///   SP 800-90C</A> requirements.
+    ///  be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy. The bytes must
+    ///  meet <A HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
+    ///  SP 800-90C</A> requirements.
     virtual unsigned int MinEntropyLength() const=0;
 
     /// \brief Provides the maximum entropy size
-    /// \returns The maximum entropy size that can be consumed by the generator, in bytes
+    /// \return The maximum entropy size that can be consumed by the generator, in bytes
     /// \details The equivalent class constant is <tt>MAXIMUM_ENTROPY</tt>. The bytes must
-    ///   meet <A HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
-    ///   SP 800-90C</A> requirements. <tt>MAXIMUM_ENTROPY</tt> has been reduced from
-    ///   2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.
+    ///  meet <A HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or
+    ///  SP 800-90C</A> requirements. <tt>MAXIMUM_ENTROPY</tt> has been reduced from
+    ///  2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.
     virtual unsigned int MaxEntropyLength() const=0;
 
     /// \brief Provides the minimum nonce size
-    /// \returns The minimum nonce size recommended for the generator, in bytes
+    /// \return The minimum nonce size recommended for the generator, in bytes
     /// \details The equivalent class constant is <tt>MINIMUM_NONCE</tt>. If a nonce is not
-    ///   required then <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a
-    ///   nonce, while <tt>HMAC_DRBG</tt> and <tt>CTR_DRBG</tt> require a nonce.
+    ///  required then <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a
+    ///  nonce, while <tt>HMAC_DRBG</tt> and <tt>CTR_DRBG</tt> require a nonce.
     virtual unsigned int MinNonceLength() const=0;
 
     /// \brief Provides the maximum nonce size
-    /// \returns The maximum nonce that can be consumed by the generator, in bytes
+    /// \return The maximum nonce that can be consumed by the generator, in bytes
     /// \details The equivalent class constant is <tt>MAXIMUM_NONCE</tt>. <tt>MAXIMUM_NONCE</tt>
-    ///   has been reduced from 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.
-    ///   If a nonce is not required then <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not
-    ///   require a nonce, while <tt>HMAC_DRBG</tt> and <tt>CTR_DRBG</tt> require a nonce.
+    ///  has been reduced from 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.
+    ///  If a nonce is not required then <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not
+    ///  require a nonce, while <tt>HMAC_DRBG</tt> and <tt>CTR_DRBG</tt> require a nonce.
     virtual unsigned int MaxNonceLength() const=0;
 
     /// \brief Provides the maximum size of a request to GenerateBlock
-    /// \returns The the maximum size of a request to GenerateBlock(), in bytes
+    /// \return The maximum size of a request to GenerateBlock(), in bytes
     /// \details The equivalent class constant is <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
     virtual unsigned int MaxBytesPerRequest() const=0;
 
     /// \brief Provides the maximum number of requests before a reseed
-    /// \returns The the maximum number of requests before a reseed, in bytes
+    /// \return The maximum number of requests before a reseed, in bytes
     /// \details The equivalent class constant is <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt>.
-    ///   <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt> has been reduced from 2<sup>48</sup> to <tt>INT_MAX</tt>
-    ///   to fit the underlying C++ datatype.
+    ///  <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt> has been reduced from 2<sup>48</sup> to <tt>INT_MAX</tt>
+    ///  to fit the underlying C++ datatype.
     virtual unsigned int MaxRequestBeforeReseed() const=0;
 
 protected:
@@ -150,31 +152,33 @@ protected:
 /// \tparam SEEDLENGTH seed length, in bytes
 /// \brief Hash_DRBG from SP 800-90A Rev 1 (June 2015)
 /// \details The NIST Hash DRBG is instantiated with a number of parameters. Two of the parameters,
-///   Security Strength and Seed Length, depend on the hash and are specified as template parameters.
-///   The remaining parameters are included in the class. The parameters and their values are listed
-///   in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).
+///  Security Strength and Seed Length, depend on the hash and are specified as template parameters.
+///  The remaining parameters are included in the class. The parameters and their values are listed
+///  in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).
 /// \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto
-///   2<sup>48</sup> requests before a reseed. However, Hash_DRBG limits it to <tt>INT_MAX</tt> due
-///   to the limited data range of an int.
+///  2<sup>48</sup> requests before a reseed. However, Hash_DRBG limits it to <tt>INT_MAX</tt> due
+///  to the limited data range of an int.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
-///   for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
+///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
 /// \since Crypto++ 6.0
 template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
 class Hash_DRBG : public NIST_DRBG, public NotCopyable
 {
 public:
-    CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
-    CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
-    CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
-    CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
-    CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
-    CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
-    CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
-    CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX)
+    CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
+    CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
+    CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
+    CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
+    CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
+    CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
+    CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
+    CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
 
     static std::string StaticAlgorithmName() { return std::string("Hash_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); }
 
@@ -185,28 +189,33 @@ public:
     /// \param nonceLength the size of the nonce buffer
     /// \param personalization additional input to instantiate the generator
     /// \param personalizationLength the size of the personalization buffer
-    /// \throws NIST_DRBG::Err if the generator is instantiated with insufficient entropy
+    /// \throw NIST_DRBG::Err if the generator is instantiated with insufficient entropy
     /// \details All NIST DRBGs must be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy.
-    ///   The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
-    ///   SP 800-90B or SP 800-90C</A> requirements.
+    ///  The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
+    ///  SP 800-90B or SP 800-90C</A> requirements.
     /// \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,
-    ///   then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
+    ///  then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
     /// \details An example of instantiating a SHA256 generator is shown below.
-    ///   The example provides more entropy than required for SHA256. The <tt>NonblockingRng</tt> meets the
-    ///   requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A>.
-    ///   RDRAND() and RDSEED() generators would work as well.
+    ///  The example provides more entropy than required for SHA256. The <tt>NonblockingRng</tt> meets the
+    ///  requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A>.
+    ///  RDRAND() and RDSEED() generators would work as well.
     /// <pre>
-    ///    SecByteBlock entropy(48), result(128);
-    ///    NonblockingRng prng;
-    ///    RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
+    ///   SecByteBlock entropy(48), result(128);
+    ///   NonblockingRng prng;
+    ///   RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
     ///
-    ///    Hash_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);
-    ///    drbg.GenerateBlock(result, result.size());
+    ///   Hash_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);
+    ///   drbg.GenerateBlock(result, result.size());
     /// </pre>
     Hash_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR,
         size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0)
         : NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH), m_reseed(0)
     {
+        if (m_c.data())  // GCC analyzer warning
+            std::memset(m_c.data(), 0x00, m_c.size());
+        if (m_v.data())  // GCC analyzer warning
+            std::memset(m_v.data(), 0x00, m_v.size());
+
         if (entropy != NULLPTR && entropyLength != 0)
             DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
     }
@@ -232,6 +241,9 @@ public:
     void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
         {return Hash_Generate(additional, additionaLength, output, size);}
 
+    std::string AlgorithmProvider() const
+        {/*Hack*/HASH hash; return hash.AlgorithmProvider();}
+
 protected:
     // 10.1.1.2 Instantiation of Hash_DRBG (p.39)
     void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
@@ -248,7 +260,8 @@ protected:
         const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen);
 
 private:
-    SecByteBlock m_c, m_v;
+    HASH m_hash;
+    SecByteBlock m_c, m_v, m_temp;
     word64 m_reseed;
 };
 
@@ -264,30 +277,32 @@ private:
 /// \tparam SEEDLENGTH seed length, in bytes
 /// \brief HMAC_DRBG from SP 800-90A Rev 1 (June 2015)
 /// \details The NIST HMAC DRBG is instantiated with a number of parameters. Two of the parameters,
-///   Security Strength and Seed Length, depend on the hash and are specified as template parameters.
-///   The remaining parameters are included in the class. The parameters and their values are listed
-///   in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).
+///  Security Strength and Seed Length, depend on the hash and are specified as template parameters.
+///  The remaining parameters are included in the class. The parameters and their values are listed
+///  in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).
 /// \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto 2<sup>48</sup> requests
-///   before a reseed. However, HMAC_DRBG limits it to <tt>INT_MAX</tt> due to the limited data range of an int.
+///  before a reseed. However, HMAC_DRBG limits it to <tt>INT_MAX</tt> due to the limited data range of an int.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
-///   for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
+///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
 /// \since Crypto++ 6.0
 template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
 class HMAC_DRBG : public NIST_DRBG, public NotCopyable
 {
 public:
-    CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
-    CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
-    CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
-    CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
-    CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
-    CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
-    CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
-    CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
-    CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX)
+    CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
+    CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
+    CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
+    CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
+    CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
+    CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
+    CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
+    CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
+    CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
 
     static std::string StaticAlgorithmName() { return std::string("HMAC_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); }
 
@@ -298,28 +313,33 @@ public:
     /// \param nonceLength the size of the nonce buffer
     /// \param personalization additional input to instantiate the generator
     /// \param personalizationLength the size of the personalization buffer
-    /// \throws NIST_DRBG::Err if the generator is instantiated with insufficient entropy
+    /// \throw NIST_DRBG::Err if the generator is instantiated with insufficient entropy
     /// \details All NIST DRBGs must be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy.
-    ///   The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
-    ///   SP 800-90B or SP 800-90C</A> requirements.
+    ///  The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
+    ///  SP 800-90B or SP 800-90C</A> requirements.
     /// \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,
-    ///   then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
+    ///  then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
     /// \details An example of instantiating a SHA256 generator is shown below.
-    ///   The example provides more entropy than required for SHA256. The <tt>NonblockingRng</tt> meets the
-    ///   requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A>.
-    ///   RDRAND() and RDSEED() generators would work as well.
+    ///  The example provides more entropy than required for SHA256. The <tt>NonblockingRng</tt> meets the
+    ///  requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A>.
+    ///  RDRAND() and RDSEED() generators would work as well.
     /// <pre>
-    ///    SecByteBlock entropy(48), result(128);
-    ///    NonblockingRng prng;
-    ///    RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
+    ///   SecByteBlock entropy(48), result(128);
+    ///   NonblockingRng prng;
+    ///   RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
     ///
-    ///    HMAC_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);
-    ///    drbg.GenerateBlock(result, result.size());
+    ///   HMAC_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);
+    ///   drbg.GenerateBlock(result, result.size());
     /// </pre>
     HMAC_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR,
         size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0)
         : NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE), m_reseed(0)
     {
+        if (m_k.data())  // GCC analyzer warning
+            std::memset(m_k, 0x00, m_k.size());
+        if (m_v.data())  // GCC analyzer warning
+            std::memset(m_v, 0x00, m_v.size());
+
         if (entropy != NULLPTR && entropyLength != 0)
             DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
     }
@@ -345,6 +365,9 @@ public:
     void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
         {return HMAC_Generate(additional, additionaLength, output, size);}
 
+    std::string AlgorithmProvider() const
+        {/*Hack*/HASH hash; return hash.AlgorithmProvider();}
+
 protected:
     // 10.1.2.3 Instantiation of HMAC_DRBG (p.45)
     void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
@@ -360,6 +383,7 @@ protected:
     void HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3);
 
 private:
+    HMAC<HASH> m_hmac;
     SecByteBlock m_k, m_v;
     word64 m_reseed;
 };
@@ -445,20 +469,19 @@ void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Generate(const byte* additional
     // Step 2
     if (additional && additionaLength)
     {
-        HASH hash;
         const byte two = 2;
-        SecByteBlock w(HASH::DIGESTSIZE);
+        m_temp.New(HASH::DIGESTSIZE);
 
-        hash.Update(&two, 1);
-        hash.Update(m_v, m_v.size());
-        hash.Update(additional, additionaLength);
-        hash.Final(w);
+        m_hash.Update(&two, 1);
+        m_hash.Update(m_v, m_v.size());
+        m_hash.Update(additional, additionaLength);
+        m_hash.Final(m_temp);
 
         CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
         int carry=0, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
         while (j>=0)
         {
-            carry = m_v[i] + w[j] + carry;
+            carry = m_v[i] + m_temp[j] + carry;
             m_v[i] = static_cast<byte>(carry);
             i--; j--; carry >>= 8;
         }
@@ -472,84 +495,41 @@ void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Generate(const byte* additional
 
     // Step 3
     {
-        HASH hash;
-        SecByteBlock data(m_v);
-
+        m_temp.Assign(m_v);
         while (size)
         {
-            hash.Update(data, data.size());
+            m_hash.Update(m_temp, m_temp.size());
             size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
-            hash.TruncatedFinal(output, count);
+            m_hash.TruncatedFinal(output, count);
 
-            IncrementCounterByOne(data, static_cast<unsigned int>(data.size()));
+            IncrementCounterByOne(m_temp, static_cast<unsigned int>(m_temp.size()));
             size -= count; output += count;
         }
     }
 
     // Steps 4-7
     {
-        HASH hash;
         const byte three = 3;
-        SecByteBlock h(HASH::DIGESTSIZE);
+        m_temp.New(HASH::DIGESTSIZE);
 
-        hash.Update(&three, 1);
-        hash.Update(m_v, m_v.size());
-        hash.Final(h);
+        m_hash.Update(&three, 1);
+        m_hash.Update(m_v, m_v.size());
+        m_hash.Final(m_temp);
 
         CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
         CRYPTOPP_ASSERT(HASH::DIGESTSIZE >= sizeof(m_reseed));
         int carry=0, k=sizeof(m_reseed)-1, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
 
-        // Using Integer class slows things down by about 8 cpb.
-        // Using word128 and word64 benefits the first loop only by about 2 cpb.
-#if defined(CRYPTOPP_WORD128_AVAILABLE)
-        byte* p1 = m_v.begin()+SEEDLENGTH-8;
-        byte* p2 = m_c.begin()+SEEDLENGTH-8;
-        byte* p3 = h.begin()+HASH::DIGESTSIZE-8;
-
-        const word64 w1 = GetWord<word64>(false, BIG_ENDIAN_ORDER, p1);
-        const word64 w2 = GetWord<word64>(false, BIG_ENDIAN_ORDER, p2);
-        const word64 w3 = GetWord<word64>(false, BIG_ENDIAN_ORDER, p3);
-        const word64 w4 = m_reseed;
-
-        word128 r = static_cast<word128>(w1) + w2 + w3 + w4;
-        PutWord(false, BIG_ENDIAN_ORDER, p1, static_cast<word64>(r));
-        i -= 8; j -= 8; k=0; carry = static_cast<int>(r >> 64);
-
-        // The default implementation and a couple of others cause a crash in
-        // VS2005, VS2008 and VS2105. This seems to work with all MS compilers.
-#elif defined(CRYPTOPP_MSC_VERSION)
-        byte* p1 = m_v.begin()+SEEDLENGTH-8;
-        byte* p2 = m_c.begin()+SEEDLENGTH-8;
-        byte* p3 = h.begin()+HASH::DIGESTSIZE-8;
-
-        const word64 w1 = GetWord<word64>(false, BIG_ENDIAN_ORDER, p1);
-        const word64 w2 = GetWord<word64>(false, BIG_ENDIAN_ORDER, p2);
-        const word64 w3 = GetWord<word64>(false, BIG_ENDIAN_ORDER, p3);
-        const word64 w4 = m_reseed;
-
-        const word64 r1 = (w1 & 0xffffffff) + (w2 & 0xffffffff) + (w3 & 0xffffffff) + (w4 & 0xffffffff);
-        carry = static_cast<int>(r1 >> 32);
-        const word64 r2 = (w1 >> 32) + (w2 >> 32) + (w3 >> 32) + (w4 >> 32) + carry;
-        carry = static_cast<int>(r2 >> 32);
-
-        const word64 r = (r2 << 32) + (r1 & 0xffffffff);
-        PutWord(false, BIG_ENDIAN_ORDER, p1, r);
-        i -= 8; j -= 8; k=0;
-
-        // Default implementation, but slower on some machines.
-#else
         while (k>=0)
         {
-            carry = m_v[i] + m_c[i] + h[j] + GetByte<word64>(BIG_ENDIAN_ORDER, m_reseed, k) + carry;
+            carry = m_v[i] + m_c[i] + m_temp[j] + GetByte<word64>(BIG_ENDIAN_ORDER, m_reseed, k) + carry;
             m_v[i] = static_cast<byte>(carry);
             i--; j--; k--; carry >>= 8;
         }
-#endif
 
         while (j>=0)
         {
-            carry = m_v[i] + m_c[i] + h[j] + carry;
+            carry = m_v[i] + m_c[i] + m_temp[j] + carry;
             m_v[i] = static_cast<byte>(carry);
             i--; j--; carry >>= 8;
         }
@@ -560,9 +540,6 @@ void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Generate(const byte* additional
             m_v[i] = static_cast<byte>(carry);
             i--; carry >>= 8;
         }
-
-        // CRYPTOPP_WORD128_AVAILABLE causes -Wunused-but-set-variable
-        CRYPTOPP_UNUSED(k);
     }
 
     m_reseed++;
@@ -573,26 +550,25 @@ template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
     const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen)
 {
-    HASH hash;
     byte counter = 1;
     word32 bits = ConditionalByteReverse(BIG_ENDIAN_ORDER, static_cast<word32>(outlen*8));
 
     while (outlen)
     {
-        hash.Update(&counter, 1);
-        hash.Update(reinterpret_cast<const byte*>(&bits), 4);
+        m_hash.Update(&counter, 1);
+        m_hash.Update(reinterpret_cast<const byte*>(&bits), 4);
 
         if (input1 && inlen1)
-            hash.Update(input1, inlen1);
+            m_hash.Update(input1, inlen1);
         if (input2 && inlen2)
-            hash.Update(input2, inlen2);
+            m_hash.Update(input2, inlen2);
         if (input3 && inlen3)
-            hash.Update(input3, inlen3);
+            m_hash.Update(input3, inlen3);
         if (input4 && inlen4)
-            hash.Update(input4, inlen4);
+            m_hash.Update(input4, inlen4);
 
         size_t count = STDMIN(outlen, (size_t)HASH::DIGESTSIZE);
-        hash.TruncatedFinal(output, count);
+        m_hash.TruncatedFinal(output, count);
 
         output += count; outlen -= count;
         counter++;
@@ -670,17 +646,15 @@ void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::HMAC_Generate(const byte* additional
         HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
 
     // Step 3
-    HMAC<HASH> hmac;
-    hmac.SetKey(m_k, m_k.size());
+    m_hmac.SetKey(m_k, m_k.size());
 
     while (size)
     {
-        hmac.Update(m_v, m_v.size());
-        hmac.TruncatedFinal(m_v, m_v.size());
+        m_hmac.Update(m_v, m_v.size());
+        m_hmac.TruncatedFinal(m_v, m_v.size());
 
         size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
-        memcpy(output, m_v, count);
-
+        std::memcpy(output, m_v, count);
         size -= count; output += count;
     }
 
@@ -693,51 +667,50 @@ template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3)
 {
     const byte zero = 0, one = 1;
-    HMAC<HASH> hmac;
 
     // Step 1
-    hmac.SetKey(m_k, m_k.size());
-    hmac.Update(m_v, m_v.size());
-    hmac.Update(&zero, 1);
+    m_hmac.SetKey(m_k, m_k.size());
+    m_hmac.Update(m_v, m_v.size());
+    m_hmac.Update(&zero, 1);
 
     if (input1 && inlen1)
-        hmac.Update(input1, inlen1);
+        m_hmac.Update(input1, inlen1);
     if (input2 && inlen2)
-        hmac.Update(input2, inlen2);
+        m_hmac.Update(input2, inlen2);
     if (input3 && inlen3)
-        hmac.Update(input3, inlen3);
+        m_hmac.Update(input3, inlen3);
 
-    hmac.TruncatedFinal(m_k, m_k.size());
+    m_hmac.TruncatedFinal(m_k, m_k.size());
 
     // Step 2
-    hmac.SetKey(m_k, m_k.size());
-    hmac.Update(m_v, m_v.size());
+    m_hmac.SetKey(m_k, m_k.size());
+    m_hmac.Update(m_v, m_v.size());
 
-    hmac.TruncatedFinal(m_v, m_v.size());
+    m_hmac.TruncatedFinal(m_v, m_v.size());
 
     // Step 3
     if ((inlen1 | inlen2 | inlen3) == 0)
         return;
 
     // Step 4
-    hmac.SetKey(m_k, m_k.size());
-    hmac.Update(m_v, m_v.size());
-    hmac.Update(&one, 1);
+    m_hmac.SetKey(m_k, m_k.size());
+    m_hmac.Update(m_v, m_v.size());
+    m_hmac.Update(&one, 1);
 
     if (input1 && inlen1)
-        hmac.Update(input1, inlen1);
+        m_hmac.Update(input1, inlen1);
     if (input2 && inlen2)
-        hmac.Update(input2, inlen2);
+        m_hmac.Update(input2, inlen2);
     if (input3 && inlen3)
-        hmac.Update(input3, inlen3);
+        m_hmac.Update(input3, inlen3);
 
-    hmac.TruncatedFinal(m_k, m_k.size());
+    m_hmac.TruncatedFinal(m_k, m_k.size());
 
     // Step 5
-    hmac.SetKey(m_k, m_k.size());
-    hmac.Update(m_v, m_v.size());
+    m_hmac.SetKey(m_k, m_k.size());
+    m_hmac.Update(m_v, m_v.size());
 
-    hmac.TruncatedFinal(m_v, m_v.size());
+    m_hmac.TruncatedFinal(m_v, m_v.size());
 }
 
 NAMESPACE_END

+ 16 - 5
include/cryptlib/dsa.h

@@ -13,11 +13,14 @@ NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief DSA Signature Format
 /// \details The DSA signature format used by Crypto++ is as defined by IEEE P1363.
-///   Java and .Net use the DER format, and OpenPGP uses the OpenPGP format.
+///  OpenSSL, Java and .Net use the DER format, and OpenPGP uses the OpenPGP format.
+/// \sa <A HREF="http://www.cryptopp.com/wiki/DSAConvertSignatureFormat">DSAConvertSignatureFormat</A>
+///  on the Crypto++ wiki.
+/// \since Crypto++ 1.0
 enum DSASignatureFormat {
 	/// \brief Crypto++ native signature encoding format
 	DSA_P1363,
-	/// \brief signature encoding format used by Java and .Net
+	/// \brief signature encoding format used by OpenSSL, Java and .Net
 	DSA_DER,
 	/// \brief OpenPGP signature encoding format
 	DSA_OPENPGP
@@ -30,13 +33,21 @@ enum DSASignatureFormat {
 /// \param signature byte buffer for the existing signature encoding
 /// \param signatureLen the length of the existing signature encoding buffer
 /// \param fromFormat the source signature format
+/// \return the number of bytes written during encoding
 /// \details This function converts between these formats, and returns length
-///   of signature in the target format. If <tt>toFormat == DSA_P1363</tt>, then
-///   <tt>bufferSize</tt> must equal <tt>publicKey.SignatureLength()</tt>
+///  of signature in the target format. If <tt>toFormat == DSA_P1363</tt>, then
+///  <tt>bufferSize</tt> must equal <tt>publicKey.SignatureLength()</tt> or
+///  <tt>verifier.SignatureLength()</tt>.
+/// \details If the destination buffer is too small then the output of the
+///  encoded <tt>r</tt> and <tt>s</tt> will be truncated. Be sure to provide
+///  an adequately sized buffer and check the return value for the number of
+///  bytes written.
+/// \sa <A HREF="http://www.cryptopp.com/wiki/DSAConvertSignatureFormat">DSAConvertSignatureFormat</A>
+///  on the Crypto++ wiki.
 /// \since Crypto++ 1.0
 size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat,
 	const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat);
 
 NAMESPACE_END
 
-#endif
+#endif  // CRYPTOPP_DSA_H

+ 4 - 0
include/cryptlib/eax.h

@@ -21,6 +21,8 @@ public:
 	// AuthenticatedSymmetricCipher
 	std::string AlgorithmName() const
 		{return GetMAC().GetCipher().AlgorithmName() + std::string("/EAX");}
+	std::string AlgorithmProvider() const
+		{return GetMAC().GetCipher().AlgorithmProvider();}
 	size_t MinKeyLength() const
 		{return GetMAC().MinKeyLength();}
 	size_t MaxKeyLength() const
@@ -76,6 +78,8 @@ class EAX_Final : public EAX_Base
 public:
 	static std::string StaticAlgorithmName()
 		{return T_BlockCipher::StaticAlgorithmName() + std::string("/EAX");}
+	std::string AlgorithmProvider() const
+		{return m_cmac.AlgorithmProvider();}
 	bool IsForwardTransformation() const
 		{return T_IsEncryption;}
 

+ 2 - 3
include/cryptlib/ec2n.h

@@ -3,7 +3,6 @@
 /// \file ec2n.h
 /// \brief Classes for Elliptic Curves over binary fields
 
-
 #ifndef CRYPTOPP_EC2N_H
 #define CRYPTOPP_EC2N_H
 
@@ -45,7 +44,7 @@ public:
 
 	/// \brief Construct an EC2N from BER encoded parameters
 	/// \param bt BufferedTransformation derived object
-	/// \details This constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
+	/// \details This constructor will decode and extract the fields fieldID and curve of the sequence ECParameters
 	EC2N(BufferedTransformation &bt);
 
 	/// \brief Encode the fields fieldID and curve of the sequence ECParameters
@@ -120,7 +119,7 @@ public:
 	void SetCurve(const EC2N &ec) {m_ec = ec;}
 
 	/// \brief Get the elliptic curve
-	/// \returns EC2N curve
+	/// \return EC2N curve
 	/// \details GetCurve() is not inherited
 	const EC2N & GetCurve() const {return m_ec;}
 

+ 65 - 42
include/cryptlib/eccrypto.h

@@ -22,6 +22,8 @@
 #include "ecp.h"
 #include "ec2n.h"
 
+#include <iosfwd>
+
 #if CRYPTOPP_MSC_VERSION
 # pragma warning(push)
 # pragma warning(disable: 4231 4275)
@@ -32,7 +34,7 @@ NAMESPACE_BEGIN(CryptoPP)
 /// \brief Elliptic Curve Parameters
 /// \tparam EC elliptic curve field
 /// \details This class corresponds to the ASN.1 sequence of the same name
-///   in ANSI X9.62 and SEC 1. EC is currently defined for ECP and EC2N.
+///  in ANSI X9.62 and SEC 1. EC is currently defined for ECP and EC2N.
 template <class EC>
 class DL_GroupParameters_EC : public DL_GroupParametersImpl<EcPrecomputation<EC> >
 {
@@ -168,6 +170,8 @@ protected:
 	mutable bool m_compress, m_encodeAsOID;		// presentation details
 };
 
+inline std::ostream& operator<<(std::ostream& os, const DL_GroupParameters_EC<ECP>::Element& obj);
+
 /// \brief Elliptic Curve Discrete Log (DL) public key
 /// \tparam EC elliptic curve field
 template <class EC>
@@ -229,8 +233,8 @@ public:
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param params the EC group parameters
 	/// \details This function overload of Initialize() creates a new private key because it
-	///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-	///   then use one of the other Initialize() overloads.
+	///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+	///  then use one of the other Initialize() overloads.
 	void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> &params)
 		{this->GenerateRandom(rng, params);}
 
@@ -240,8 +244,8 @@ public:
 	/// \param G the base point
 	/// \param n the order of the base point
 	/// \details This function overload of Initialize() creates a new private key because it
-	///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-	///   then use one of the other Initialize() overloads.
+	///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+	///  then use one of the other Initialize() overloads.
 	void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
 		{this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}
 
@@ -279,7 +283,7 @@ struct ECMQV
 /// \tparam EC elliptic curve field
 /// \tparam COFACTOR_OPTION cofactor multiplication option
 /// \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
-///   Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
+///  Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
 /// \sa CofactorMultiplicationOption
 template <class EC, class COFACTOR_OPTION = typename DL_GroupParameters_EC<EC>::DefaultCofactorOption, class HASH = SHA256>
 struct ECHMQV
@@ -296,8 +300,8 @@ typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512
 /// \tparam EC elliptic curve field
 /// \tparam COFACTOR_OPTION cofactor multiplication option
 /// \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
-///   <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
-///   Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
+///  <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
+///  Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
 /// \sa CofactorMultiplicationOption
 template <class EC, class COFACTOR_OPTION = typename DL_GroupParameters_EC<EC>::DefaultCofactorOption, class HASH = SHA256>
 struct ECFHMQV
@@ -346,7 +350,7 @@ public:
 /// \brief Elliptic Curve DSA (ECDSA) signature algorithm based on RFC 6979
 /// \tparam EC elliptic curve field
 /// \sa <a href="http://tools.ietf.org/rfc/rfc6979.txt">RFC 6979, Deterministic Usage of the
-///   Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)</a>
+///  Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)</a>
 /// \since Crypto++ 6.0
 template <class EC, class H>
 class DL_Algorithm_ECDSA_RFC6979 : public DL_Algorithm_DSA_RFC6979<typename EC::Point, H>
@@ -378,7 +382,7 @@ struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_Signat
 /// \tparam EC elliptic curve field
 /// \tparam H HashTransformation derived class
 /// \sa <a href="http://tools.ietf.org/rfc/rfc6979.txt">Deterministic Usage of the
-///   Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)</a>
+///  Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)</a>
 /// \since Crypto++ 6.0
 template <class EC, class H>
 struct ECDSA_RFC6979 : public DL_SS<
@@ -446,8 +450,8 @@ public:
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param params the EC group parameters
 	/// \details This function overload of Initialize() creates a new private key because it
-	///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-	///   then use one of the other Initialize() overloads.
+	///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+	///  then use one of the other Initialize() overloads.
 	void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> &params)
 		{this->GenerateRandom(rng, params);}
 
@@ -457,8 +461,8 @@ public:
 	/// \param G the base point
 	/// \param n the order of the base point
 	/// \details This function overload of Initialize() creates a new private key because it
-	///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-	///   then use one of the other Initialize() overloads.
+	///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+	///  then use one of the other Initialize() overloads.
 	void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
 		{this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}
 
@@ -566,8 +570,8 @@ public:
 /// \tparam EC elliptic curve field
 /// \tparam H HashTransformation derived class
 /// \sa Erwin Hess, Marcus Schafheutle, and Pascale Serf <A
-///   HREF="http://www.teletrust.de/fileadmin/files/oid/ecgdsa_final.pdf">The Digital Signature Scheme
-///   ECGDSA (October 24, 2006)</A>
+///  HREF="http://www.teletrust.de/fileadmin/files/oid/ecgdsa_final.pdf">The Digital Signature Scheme
+///  ECGDSA (October 24, 2006)</A>
 /// \since Crypto++ 6.0
 template <class EC, class H>
 struct ECGDSA : public DL_SS<
@@ -583,36 +587,22 @@ struct ECGDSA : public DL_SS<
 
 /// \brief Elliptic Curve Integrated Encryption Scheme
 /// \tparam COFACTOR_OPTION cofactor multiplication option
-/// \tparam HASH HashTransformation derived class used for key drivation and MAC computation
+/// \tparam HASH HashTransformation derived class used for key derivation and MAC computation
 /// \tparam DHAES_MODE flag indicating if the MAC includes additional context parameters such as <em>u·V</em>, <em>v·U</em> and label
 /// \tparam LABEL_OCTETS flag indicating if the label size is specified in octets or bits
 /// \details ECIES is an Elliptic Curve based Integrated Encryption Scheme (IES). The scheme combines a Key Encapsulation
-///   Method (KEM) with a Data Encapsulation Method (DEM) and a MAC tag. The scheme is
-///   <A HREF="http://en.wikipedia.org/wiki/ciphertext_indistinguishability">IND-CCA2</A>, which is a strong notion of security.
-///   You should prefer an Integrated Encryption Scheme over homegrown schemes.
-/// \details The library's original implementation is based on an early P1363 draft, which itself appears to be based on an early Certicom
-///   SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used the early draft in its Integrated Ecryption
-///   Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
-/// \details If you desire an Integrated Encryption Scheme with Crypto++ 4.2 compatibility, then use the ECIES template class with
-///   <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
-/// \details If you desire an Integrated Encryption Scheme with Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES
-///   template class with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
+///  Method (KEM) with a Data Encapsulation Method (DEM) and a MAC tag. The scheme is
+///  <A HREF="http://en.wikipedia.org/wiki/ciphertext_indistinguishability">IND-CCA2</A>, which is a strong notion of security.
+///  You should prefer an Integrated Encryption Scheme over homegrown schemes.
+/// \details If you desire an Integrated Encryption Scheme with Crypto++ 4.2 compatibility, then use the ECIES_P1363.
+///  If you desire an Integrated Encryption Scheme compatible with Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES
+///  template class with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
 /// \details The default template parameters ensure compatibility with Bouncy Castle 1.54 and Botan 1.11. The combination of
-///   <tt>IncompatibleCofactorMultiplication</tt> and <tt>DHAES_MODE=true</tt> is recommended for best efficiency and security.
-///   SHA1 is used for compatibility reasons, but it can be changed if desired. SHA-256 or another hash will likely improve the
-///   security provided by the MAC. The hash is also used in the key derivation function as a PRF.
-/// \details Below is an example of constructing a Crypto++ 4.2 compatible ECIES encryptor and decryptor.
-/// <pre>
-///     AutoSeededRandomPool prng;
-///     DL_PrivateKey_EC<ECP> key;
-///     key.Initialize(prng, ASN1::secp160r1());
-///
-///     ECIES<ECP,SHA1,NoCofactorMultiplication,true,true>::Decryptor decryptor(key);
-///     ECIES<ECP,SHA1,NoCofactorMultiplication,true,true>::Encryptor encryptor(decryptor);
-/// </pre>
-/// \sa DLIES, <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">Elliptic Curve Integrated Encryption Scheme (ECIES)</a>,
-///   Martínez, Encinas, and Ávila's <A HREF="http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf">A Survey of the Elliptic
-///   Curve Integrated Encryption Schemes</A>
+///  <tt>IncompatibleCofactorMultiplication</tt> and <tt>DHAES_MODE=true</tt> is recommended for best efficiency and security.
+///  SHA1 is used for compatibility reasons, but it can be changed if desired.
+/// \sa DLIES, ECIES_P1363, <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">Elliptic Curve Integrated Encryption Scheme (ECIES)</a>,
+///  Martínez, Encinas, and Ávila's <A HREF="http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf">A Survey of the Elliptic
+///  Curve Integrated Encryption Schemes</A>
 /// \since Crypto++ 4.0, Crypto++ 5.7 for Bouncy Castle and Botan compatibility
 template <class EC, class HASH = SHA1, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true, bool LABEL_OCTETS = false>
 struct ECIES
@@ -627,6 +617,39 @@ struct ECIES
 	CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECIES";}
 };
 
+/// \brief Elliptic Curve Integrated Encryption Scheme for P1363
+/// \tparam COFACTOR_OPTION cofactor multiplication option
+/// \tparam HASH HashTransformation derived class used for key derivation and MAC computation
+/// \details ECIES_P1363 is an Elliptic Curve based Integrated Encryption Scheme (IES) for P1363. The scheme combines a Key Encapsulation
+///  Method (KEM) with a Data Encapsulation Method (DEM) and a MAC tag. The scheme is
+///  <A HREF="http://en.wikipedia.org/wiki/ciphertext_indistinguishability">IND-CCA2</A>, which is a strong notion of security.
+///  You should prefer an Integrated Encryption Scheme over homegrown schemes.
+/// \details The library's original implementation is based on an early P1363 draft, which itself appears to be based on an early Certicom
+///  SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used the early draft in its Integrated Enryption
+///  Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
+/// \details If you desire an Integrated Encryption Scheme with Crypto++ 4.2 compatibility, then use the ECIES_P1363.
+///  If you desire an Integrated Encryption Scheme compatible with Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES
+///  template class with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
+/// \details The default template parameters ensure compatibility with P1363. The combination of
+///  <tt>IncompatibleCofactorMultiplication</tt> and <tt>DHAES_MODE=true</tt> is recommended for best efficiency and security.
+///  SHA1 is used for compatibility reasons, but it can be changed if desired.
+/// \sa DLIES, ECIES, <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">Elliptic Curve Integrated Encryption Scheme (ECIES)</a>,
+///  Martínez, Encinas, and Ávila's <A HREF="http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf">A Survey of the Elliptic
+///  Curve Integrated Encryption Schemes</A>
+/// \since Crypto++ 4.0
+template <class EC, class HASH = SHA1, class COFACTOR_OPTION = NoCofactorMultiplication>
+struct ECIES_P1363
+	: public DL_ES<
+		DL_Keys_EC<EC>,
+		DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>,
+		DL_KeyDerivationAlgorithm_P1363<typename EC::Point, false, P1363_KDF2<HASH> >,
+		DL_EncryptionAlgorithm_Xor<HMAC<HASH>, false, true>,
+		ECIES<EC> >
+{
+	// TODO: fix this after name is standardized
+	CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECIES-P1363";}
+};
+
 NAMESPACE_END
 
 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES

+ 18 - 6
include/cryptlib/ecp.h

@@ -35,11 +35,15 @@ public:
 	/// \brief Construct an ECP
 	ECP() {}
 
-	/// \brief Copy construct an ECP
+	/// \brief Construct an ECP
 	/// \param ecp the other ECP object
-	/// \param convertToMontgomeryRepresentation flag indicating if the curve should be converted to a MontgomeryRepresentation
+	/// \param convertToMontgomeryRepresentation flag indicating if the curve
+	///  should be converted to a MontgomeryRepresentation.
+	/// \details Prior to Crypto++ 8.3 the default value for
+	///  convertToMontgomeryRepresentation was false. it was changed due to
+	///  two audit tools finding, "Signature-compatible with a copy constructor".
 	/// \sa ModularArithmetic, MontgomeryRepresentation
-	ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false);
+	ECP(const ECP &ecp, bool convertToMontgomeryRepresentation);
 
 	/// \brief Construct an ECP
 	/// \param modulus the prime modulus
@@ -50,14 +54,22 @@ public:
 
 	/// \brief Construct an ECP from BER encoded parameters
 	/// \param bt BufferedTransformation derived object
-	/// \details This constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
+	/// \details This constructor will decode and extract the fields
+	///  fieldID and curve of the sequence ECParameters
 	ECP(BufferedTransformation &bt);
 
-	/// \brief Encode the fields fieldID and curve of the sequence ECParameters
+	/// \brief DER Encode
 	/// \param bt BufferedTransformation derived object
+	/// \details DEREncode encode the fields fieldID and curve of the sequence
+	///  ECParameters
 	void DEREncode(BufferedTransformation &bt) const;
 
+	/// \brief Compare two points
+	/// \param P the first point
+	/// \param Q the second point
+	/// \return true if equal, false otherwise
 	bool Equal(const Point &P, const Point &Q) const;
+
 	const Point& Identity() const;
 	const Point& Inverse(const Point &P) const;
 	bool InversionIsFast() const {return true;}
@@ -138,7 +150,7 @@ public:
 	}
 
 	/// \brief Get the elliptic curve
-	/// \returns ECP curve
+	/// \return ECP curve
 	/// \details GetCurve() is not inherited
 	const ECP & GetCurve() const {return *m_ecOriginal;}
 

+ 9 - 9
include/cryptlib/ecpoint.h

@@ -32,13 +32,13 @@ struct CRYPTOPP_DLL ECPPoint
 
 	/// \brief Tests points for equality
 	/// \param t the other point
-	/// \returns true if the points are equal, false otherwise
+	/// \return true if the points are equal, false otherwise
 	bool operator==(const ECPPoint &t) const
 		{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
 
 	/// \brief Tests points for ordering
 	/// \param t the other point
-	/// \returns true if this point is less than other, false otherwise
+	/// \return true if this point is less than other, false otherwise
 	bool operator< (const ECPPoint &t) const
 		{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
 
@@ -65,13 +65,13 @@ struct CRYPTOPP_DLL EC2NPoint
 
 	/// \brief Tests points for equality
 	/// \param t the other point
-	/// \returns true if the points are equal, false otherwise
+	/// \return true if the points are equal, false otherwise
 	bool operator==(const EC2NPoint &t) const
 		{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
 
 	/// \brief Tests points for ordering
 	/// \param t the other point
-	/// \returns true if this point is less than other, false otherwise
+	/// \return true if this point is less than other, false otherwise
 	bool operator< (const EC2NPoint &t) const
 		{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
 
@@ -96,24 +96,24 @@ public:
 	/// \param P point which is decoded
 	/// \param bt source BufferedTransformation
 	/// \param len number of bytes to read from the BufferedTransformation
-	/// \returns true if a point was decoded, false otherwise
+	/// \return true if a point was decoded, false otherwise
 	virtual bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const =0;
 
 	/// \brief Decodes an elliptic curve point
 	/// \param P point which is decoded
 	/// \param encodedPoint byte array with the encoded point
 	/// \param len the size of the array
-	/// \returns true if a point was decoded, false otherwise
+	/// \return true if a point was decoded, false otherwise
 	virtual bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const =0;
 
 	/// \brief Verifies points on elliptic curve
 	/// \param P point to verify
-	/// \returns true if the point is valid, false otherwise
+	/// \return true if the point is valid, false otherwise
 	virtual bool VerifyPoint(const Point &P) const =0;
 
 	/// \brief Determines encoded point size
 	/// \param compressed flag indicating if the point is compressed
-	/// \returns the minimum number of bytes required to encode the point
+	/// \return the minimum number of bytes required to encode the point
 	virtual unsigned int EncodedPointSize(bool compressed = false) const =0;
 
 	/// \brief Encodes an elliptic curve point
@@ -131,7 +131,7 @@ public:
 
 	/// \brief BER Decodes an elliptic curve point
 	/// \param bt source BufferedTransformation
-	/// \returns the decoded elliptic curve point
+	/// \return the decoded elliptic curve point
 	virtual Point BERDecodePoint(BufferedTransformation &bt) const =0;
 
 	/// \brief DER Encodes an elliptic curve point

+ 175 - 16
include/cryptlib/elgamal.h

@@ -11,23 +11,27 @@
 #include "integer.h"
 #include "gfpcrypt.h"
 #include "pubkey.h"
-#include "dsa.h"
 #include "misc.h"
+#include "oids.h"
+#include "dsa.h"
+#include "asn.h"
 
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief ElGamal key agreement and encryption schemes base class
 /// \since Crypto++ 1.0
-class CRYPTOPP_NO_VTABLE ElGamalBase : public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>,
-					public DL_KeyDerivationAlgorithm<Integer>,
-					public DL_SymmetricEncryptionAlgorithm
+class CRYPTOPP_NO_VTABLE ElGamalBase :
+	public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>,
+	public DL_KeyDerivationAlgorithm<Integer>,
+	public DL_SymmetricEncryptionAlgorithm
 {
 public:
 	virtual ~ElGamalBase() {}
 
 	void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const
 	{
-		CRYPTOPP_UNUSED(groupParams), CRYPTOPP_UNUSED(ephemeralPublicKey), CRYPTOPP_UNUSED(derivationParams);
+		CRYPTOPP_UNUSED(groupParams); CRYPTOPP_UNUSED(ephemeralPublicKey);
+		CRYPTOPP_UNUSED(derivationParams);
 		agreedElement.Encode(derivedKey, derivedLength);
 	}
 
@@ -49,6 +53,8 @@ public:
 	size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const
 	{
 		unsigned int len = GetGroupParameters().GetModulus().ByteCount();
+		CRYPTOPP_ASSERT(len >= 3);
+
 		if (cipherTextLength == len)
 			return STDMIN(255U, len-3);
 		else
@@ -63,7 +69,7 @@ public:
 
 		SecByteBlock block(modulusLen-1);
 		rng.GenerateBlock(block, modulusLen-2-plainTextLength);
-		memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
+		std::memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
 		block[modulusLen-2] = (byte)plainTextLength;
 
 		a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen);
@@ -93,9 +99,14 @@ public:
 };
 
 /// \brief ElGamal key agreement and encryption schemes default implementation
+/// \tparam BASE Base class implementation
+/// \tparam SCHEME_OPTIONS Scheme options
+/// \tparam KEY ElGamal key classes
 /// \since Crypto++ 1.0
 template <class BASE, class SCHEME_OPTIONS, class KEY>
-class ElGamalObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>, public ElGamalBase
+class ElGamalObjectImpl :
+	public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>,
+	public ElGamalBase
 {
 public:
 	virtual ~ElGamalObjectImpl() {}
@@ -114,30 +125,178 @@ protected:
 	const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;}
 };
 
+/// \brief ElGamal Public Key adapter
+/// \tparam BASE PublicKey derived class
+/// \details DL_PublicKey_ElGamal provides an override for GetAlgorithmID()
+///  to utilize 1.3.14.7.2.1.1. Prior to DL_PublicKey_ElGamal, the ElGamal
+///  keys [mistakenly] used the OID from DSA due to DL_GroupParmaters_GFP().
+///  If you need to <tt>Load</tt> an ElGamal key with the wrong OID then
+///  see <A HREF="https://www.cryptopp.com/wiki/ElGamal">ElGamal</A> on
+///  the Crypto++ wiki.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/876">Issue 876</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/567">Issue 567</A>
+/// \since Crypto++ 8.3
+template <class BASE>
+struct DL_PublicKey_ElGamal : public BASE
+{
+	virtual ~DL_PublicKey_ElGamal() {}
+
+	/// \brief Retrieves the OID of the algorithm
+	/// \return OID of the algorithm
+	/// \details DL_PrivateKey_ElGamal provides an override for GetAlgorithmID()
+	///  to utilize 1.3.14.7.2.1.1. Prior to DL_PrivateKey_ElGamal, the ElGamal
+	///  keys [mistakenly] used the OID from DSA due to DL_GroupParmaters_GFP().
+	///  If you need to <tt>Load</tt> an ElGamal key with the wrong OID then
+	///  see <A HREF="https://www.cryptopp.com/wiki/ElGamal">ElGamal</A> on
+	///  the Crypto++ wiki.
+	/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/876">Issue 876</A>,
+	///  <A HREF="https://github.com/weidai11/cryptopp/issues/567">Issue 567</A>
+	virtual OID GetAlgorithmID() const {
+		return ASN1::elGamal();
+	}
+};
+
+/// \brief ElGamal Private Key adapter
+/// \tparam BASE PrivateKey derived class
+/// \details DL_PrivateKey_ElGamal provides an override for GetAlgorithmID()
+///  to utilize 1.3.14.7.2.1.1. Prior to DL_PrivateKey_ElGamal, the ElGamal
+///  keys [mistakenly] used the OID from DSA due to DL_GroupParmaters_GFP().
+///  If you need to <tt>Load</tt> an ElGamal key with the wrong OID then
+///  see <A HREF="https://www.cryptopp.com/wiki/ElGamal">ElGamal</A> on
+///  the Crypto++ wiki.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/876">Issue 876</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/567">Issue 567</A>
+/// \since Crypto++ 8.3
+template <class BASE>
+struct DL_PrivateKey_ElGamal : public BASE
+{
+	virtual ~DL_PrivateKey_ElGamal() {}
+
+	/// \brief Retrieves the OID of the algorithm
+	/// \return OID of the algorithm
+	/// \details DL_PrivateKey_ElGamal provides an override for GetAlgorithmID()
+	///  to utilize 1.3.14.7.2.1.1. Prior to DL_PrivateKey_ElGamal, the ElGamal
+	///  keys [mistakenly] used the OID from DSA due to DL_GroupParmaters_GFP().
+	///  If you need to <tt>Load</tt> an ElGamal key with the wrong OID then
+	///  see <A HREF="https://www.cryptopp.com/wiki/ElGamal">ElGamal</A> on
+	///  the Crypto++ wiki.
+	/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/876">Issue 876</A>,
+	///  <A HREF="https://github.com/weidai11/cryptopp/issues/567">Issue 567</A>
+	virtual OID GetAlgorithmID() const {
+		return ASN1::elGamal();
+	}
+
+	/// \brief Check the key for errors
+	/// \param rng RandomNumberGenerator for objects which use randomized testing
+	/// \param level level of thoroughness
+	/// \return true if the tests succeed, false otherwise
+	/// \details There are four levels of thoroughness:
+	///   <ul>
+	///   <li>0 - using this object won't cause a crash or exception
+	///   <li>1 - this object will probably function, and encrypt, sign, other
+	///           operations correctly
+	///   <li>2 - ensure this object will function correctly, and perform
+	///           reasonable security checks
+	///   <li>3 - perform reasonable security checks, and do checks that may
+	///           take a long time
+	///   </ul>
+	/// \details Level 0 does not require a RandomNumberGenerator. A NullRNG() can
+	///  be used for level 0. Level 1 may not check for weak keys and such.
+	///  Levels 2 and 3 are recommended.
+	bool Validate(RandomNumberGenerator &rng, unsigned int level) const
+	{
+		// Validate() formerly used DL_PrivateKey_GFP implementation through
+		// inheritance. However, it would reject keys from other libraries
+		// like BouncyCastle. The failure was x < q. According to ElGamal's
+		// paper and the HAC, the private key is selected in over [1,p-1],
+		// Later Tsiounis and Yung showed the lower limit as [1,q-1] in
+		// "On the Security of EIGamal Based Encryption". As such, Crypto++
+		// will generate a key in the range [1,q-1], but accept a key
+		// in [1,p-1]. Thanks to JPM for finding the reference. Also see
+		// https://github.com/weidai11/cryptopp/commit/a5a684d92986.
+
+		CRYPTOPP_ASSERT(this->GetAbstractGroupParameters().Validate(rng, level));
+		bool pass = this->GetAbstractGroupParameters().Validate(rng, level);
+
+		const Integer &p = this->GetGroupParameters().GetModulus();
+		const Integer &q = this->GetAbstractGroupParameters().GetSubgroupOrder();
+		const Integer &x = this->GetPrivateExponent();
+
+		// Changed to x < p-1 based on ElGamal's paper and the HAC.
+		CRYPTOPP_ASSERT(x.IsPositive());
+		CRYPTOPP_ASSERT(x < p-1);
+		pass = pass && x.IsPositive() && x < p-1;
+
+		if (level >= 1)
+		{
+			// Minimum security level due to Tsiounis and Yung.
+			CRYPTOPP_ASSERT(Integer::Gcd(x, q) == Integer::One());
+			pass = pass && Integer::Gcd(x, q) == Integer::One();
+		}
+		return pass;
+	}
+};
+
 /// \brief ElGamal key agreement and encryption schemes keys
-/// \details The ElGamalKeys class used DL_PrivateKey_GFP_OldFormat and DL_PublicKey_GFP_OldFormat
-///   for the PrivateKey and PublicKey typedef from about Crypto++ 1.0 through Crypto++ 5.6.5.
-///   At Crypto++ 6.0 the serialization format was cutover to standard PKCS8 and X509 encodings.
-/// \sa <A HREF="https://github.com/weidai11/cryptopp/commit/a5a684d92986e8e2">Commit a5a684d92986e8e2</A>
+/// \details ElGamalKeys provide the algorithm implementation ElGamal key
+///  agreement and encryption schemes.
+/// \details The ElGamalKeys class used <tt>DL_PrivateKey_GFP_OldFormat</tt>
+///  and <tt>DL_PublicKey_GFP_OldFormat</tt> for the <tt>PrivateKey</tt> and
+///  <tt>PublicKey</tt> from about Crypto++ 1.0 through Crypto++ 5.6.5. At
+///  Crypto++ 6.0 the serialization format was cutover to standard PKCS8 and
+///  X509 encodings.
+/// \details The ElGamalKeys class [mistakenly] used the OID for DSA from
+///  about Crypto++ 1.0 through Crypto++ 8.2. At Crypto++ 8.3 the OID was
+///  fixed and now uses ElGamal encryption, which is 1.3.14.7.2.1.1.
+///  If you need to <tt>Load</tt> an ElGamal key with the wrong OID then
+///  see <A HREF="https://www.cryptopp.com/wiki/ElGamal">ElGamal</A> on
+///  the Crypto++ wiki.
+/// \details At Crypto++ 8.6 ElGamalKeys were changed to use DL_CryptoKeys_ElGamal
+///  due to Issue 1069 and CVE-2021-40530. DL_CryptoKeys_ElGamal group parameters
+///  use the subgroup order, and not an estimated work factor.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/876">Issue 876</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/567">Issue 567</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/1059">Issue 1059</A>
+/// \since Crypto++ 1.0
 struct ElGamalKeys
 {
-	typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters;
-	typedef DL_CryptoKeys_GFP::PrivateKey PrivateKey;
-	typedef DL_CryptoKeys_GFP::PublicKey PublicKey;
+	/// \brief Implements DL_GroupParameters interface
+	typedef DL_CryptoKeys_ElGamal::GroupParameters GroupParameters;
+	/// \brief Implements DL_PrivateKey interface
+	typedef DL_PrivateKey_ElGamal<DL_CryptoKeys_ElGamal::PrivateKey> PrivateKey;
+	/// \brief Implements DL_PublicKey interface
+	typedef DL_PublicKey_ElGamal<DL_CryptoKeys_ElGamal::PublicKey> PublicKey;
 };
 
 /// \brief ElGamal encryption scheme with non-standard padding
+/// \details ElGamal provide the algorithm implementation ElGamal key
+///  agreement and encryption schemes.
+/// \details The ElGamal class [mistakenly] used the OID for DSA from about
+///  Crypto++ 1.0 through Crypto++ 8.2. At Crypto++ 8.3 the OID was fixed
+///  and now uses ElGamal encryption, which is 1.3.14.7.2.1.1.
+///  If you need to <tt>Load</tt> an ElGamal key with the wrong OID then
+///  see <A HREF="https://www.cryptopp.com/wiki/ElGamal">ElGamal</A> on
+///  the Crypto++ wiki.
+/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/876">Issue 876</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/567">Issue 567</A>
 /// \since Crypto++ 1.0
 struct ElGamal
 {
 	typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions;
+	typedef SchemeOptions::PrivateKey PrivateKey;
+	typedef SchemeOptions::PublicKey PublicKey;
 
+	/// \brief The algorithm name
+	/// \return the algorithm name
+	/// \details StaticAlgorithmName returns the algorithm's name as a static
+	///  member function.
 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";}
 
+	/// \brief Implements DL_GroupParameters interface
 	typedef SchemeOptions::GroupParameters GroupParameters;
-	/// implements PK_Encryptor interface
+	/// \brief Implements PK_Encryptor interface
 	typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor;
-	/// implements PK_Decryptor interface
+	/// \brief Implements PK_Encryptor interface
 	typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor;
 };
 

+ 12 - 12
include/cryptlib/eprecomp.h

@@ -24,28 +24,28 @@ public:
 	virtual ~DL_GroupPrecomputation() {}
 
 	/// \brief Determines if elements needs conversion
-	/// \returns true if the element needs conversion, false otherwise
+	/// \return true if the element needs conversion, false otherwise
 	/// \details NeedConversions determines if an element must convert between representations.
 	virtual bool NeedConversions() const {return false;}
 
 	/// \brief Converts an element between representations
 	/// \param v element to convert
-	/// \returns an element converted to an alternate representation for internal use
+	/// \return an element converted to an alternate representation for internal use
 	/// \details ConvertIn is used when an element must convert between representations.
 	virtual Element ConvertIn(const Element &v) const {return v;}
 
 	/// \brief Converts an element between representations
 	/// \param v element to convert
-	/// \returns an element converted from an alternate representation
+	/// \return an element converted from an alternate representation
 	virtual Element ConvertOut(const Element &v) const {return v;}
 
 	/// \brief Retrieves AbstractGroup interface
-	/// \returns GetGroup() returns the AbstractGroup interface
+	/// \return GetGroup() returns the AbstractGroup interface
 	virtual const AbstractGroup<Element> & GetGroup() const =0;
 
 	/// \brief Decodes element in DER format
 	/// \param bt BufferedTransformation object
-	/// \returns element in the group
+	/// \return element in the group
 	virtual Element BERDecodeElement(BufferedTransformation &bt) const =0;
 
 	/// \brief Encodes element in DER format
@@ -65,7 +65,7 @@ public:
 	virtual ~DL_FixedBasePrecomputation() {}
 
 	/// \brief Determines whether this object is initialized
-	/// \returns true if this object is initialized, false otherwise
+	/// \return true if this object is initialized, false otherwise
 	virtual bool IsInitialized() const =0;
 
 	/// \brief Set the base element
@@ -75,7 +75,7 @@ public:
 
 	/// \brief Get the base element
 	/// \param group the group
-	/// \returns base element in the group
+	/// \return base element in the group
 	virtual const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const =0;
 
 	/// \brief Perform precomputation
@@ -90,16 +90,16 @@ public:
 	virtual void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage) =0;
 
 	/// \brief Retrieve previously saved precomputation
-	/// \param group the the group
+	/// \param group the group
 	/// \param storedPrecomputation BufferedTransformation with the saved precomputation
-	/// \throws NotImplemented
+	/// \throw NotImplemented
 	/// \sa SupportsPrecomputation(), Precompute()
 	virtual void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) =0;
 
 	/// \brief Save precomputation for later use
-	/// \param group the the group
+	/// \param group the group
 	/// \param storedPrecomputation BufferedTransformation to write the precomputation
-	/// \throws NotImplemented
+	/// \throw NotImplemented
 	/// \sa SupportsPrecomputation(), Precompute()
 	virtual void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const =0;
 
@@ -114,7 +114,7 @@ public:
 	/// \param exponent1 the first exponent
 	/// \param pc2 the second the group precomputation
 	/// \param exponent2 the first exponent2
-	/// \returns the public element raised to the exponent
+	/// \return the public element raised to the exponent
 	/// \details CascadeExponentiateBaseAndPublicElement raises the public element to
 	///   the base element and precomputation.
 	virtual Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &pc1, const Integer &exponent1, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const =0;

+ 177 - 71
include/cryptlib/fhmqv.h

@@ -30,59 +30,148 @@ public:
 
   virtual ~FHMQV_Domain() {}
 
-  FHMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
-
+  /// \brief Construct a FHMQV domain
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
+  FHMQV_Domain(bool clientRole = true)
+    : m_role(clientRole ? RoleClient : RoleServer) {}
+
+  /// \brief Construct a FHMQV domain
+  /// \param params group parameters and options
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   FHMQV_Domain(const GroupParameters &params, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
 
+  /// \brief Construct a FHMQV domain
+  /// \param bt BufferedTransformation with group parameters and options
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.BERDecode(bt);}
-
+    {m_groupParameters.BERDecode(bt);}
+
+  /// \brief Construct a FHMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1 is passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1>
   FHMQV_Domain(T1 v1, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1);}
-
+    {m_groupParameters.Initialize(v1);}
+
+  /// \brief Construct a FHMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \tparam T2 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param v2 second parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1, class T2>
   FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1, v2);}
-
+    {m_groupParameters.Initialize(v1, v2);}
+
+  /// \brief Construct a FHMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \tparam T2 template parameter used as a constructor parameter
+  /// \tparam T3 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param v2 second parameter
+  /// \param v3 third parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1, class T2, class T3>
   FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1, v2, v3);}
-
+    {m_groupParameters.Initialize(v1, v2, v3);}
+
+  /// \brief Construct a FHMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \tparam T2 template parameter used as a constructor parameter
+  /// \tparam T3 template parameter used as a constructor parameter
+  /// \tparam T4 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param v2 second parameter
+  /// \param v3 third parameter
+  /// \param v4 third parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1, class T2, class T3, class T4>
   FHMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1, v2, v3, v4);}
+    {m_groupParameters.Initialize(v1, v2, v3, v4);}
 
 public:
 
+  /// \brief Retrieves the group parameters for this domain
+  /// \return the group parameters for this domain as a const reference
   const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
-  GroupParameters & AccessGroupParameters(){return m_groupParameters;}
-
-  CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
-
-  /// return length of agreed value produced
-  unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
-  /// return length of static private keys in this domain
-  unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
-  /// return length of static public keys in this domain
-  unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
 
-  /// generate static private key
-  /*! \pre size of privateKey == PrivateStaticKeyLength() */
+  /// \brief Retrieves the group parameters for this domain
+  /// \return the group parameters for this domain as a non-const reference
+  GroupParameters & AccessGroupParameters() {return m_groupParameters;}
+
+  /// \brief Retrieves the crypto parameters for this domain
+  /// \return the crypto parameters for this domain as a non-const reference
+  CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
+
+  /// \brief Provides the size of the agreed value
+  /// \return size of agreed value produced in this domain
+  /// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
+  ///  which means the element is encoded in a non-reversible format. A
+  ///  non-reversible format means its a raw byte array, and it lacks presentation
+  ///  format like an ASN.1 BIT_STRING or OCTET_STRING.
+  unsigned int AgreedValueLength() const
+    {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
+
+  /// \brief Provides the size of the static private key
+  /// \return size of static private keys in this domain
+  /// \details The length is calculated using the byte count of the subgroup order.
+  unsigned int StaticPrivateKeyLength() const
+    {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
+
+  /// \brief Provides the size of the static public key
+  /// \return size of static public keys in this domain
+  /// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>,
+  ///  which means the element is encoded in a reversible format. A reversible
+  ///  format means it has a presentation format, and its an ANS.1 encoded element
+  ///  or point.
+  unsigned int StaticPublicKeyLength() const
+    {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
+
+  /// \brief Generate static private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer for the generated private key in this domain
+  /// \details The private key is a random scalar used as an exponent in the range
+  ///  <tt>[1,MaxExponent()]</tt>.
+  /// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
   void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
   {
     Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
     x.Encode(privateKey, StaticPrivateKeyLength());
   }
 
-  /// generate static public key
-  /*! \pre size of publicKey == PublicStaticKeyLength() */
+  /// \brief Generate a static public key from a private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer with the previously generated private key
+  /// \param publicKey a byte buffer for the generated public key in this domain
+  /// \details The public key is an element or point on the curve, and its stored
+  ///  in a revrsible format. A reversible format means it has a presentation
+  ///  format, and its an ANS.1 encoded element or point.
+  /// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
   void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
   {
     CRYPTOPP_UNUSED(rng);
@@ -92,10 +181,22 @@ public:
     params.EncodeElement(true, y, publicKey);
   }
 
+  /// \brief Provides the size of the ephemeral private key
+  /// \return size of ephemeral private keys in this domain
+  /// \details An ephemeral private key is a private key and public key.
+  ///  The serialized size is different than a static private key.
   unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
+
+  /// \brief Provides the size of the ephemeral public key
+  /// \return size of ephemeral public keys in this domain
+  /// \details An ephemeral public key is a public key.
+  ///  The serialized size is the same as a static public key.
   unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
 
-  /// return length of ephemeral private keys in this domain
+  /// \brief Generate ephemeral private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer for the generated private key in this domain
+  /// \pre <tt>COUNTOF(privateKey) == EphemeralPrivateKeyLength()</tt>
   void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
   {
     const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
@@ -105,28 +206,46 @@ public:
     params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
   }
 
-  /// return length of ephemeral public keys in this domain
+  /// \brief Generate ephemeral public key from a private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer with the previously generated private key
+  /// \param publicKey a byte buffer for the generated public key in this domain
+  /// \pre <tt>COUNTOF(publicKey) == EphemeralPublicKeyLength()</tt>
   void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
   {
     CRYPTOPP_UNUSED(rng);
-    memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
+    std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
   }
 
-  /// derive agreed value from your private keys and couterparty's public keys, return false in case of failure
-  /*! \note The ephemeral public key will always be validated.
-  If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
-  \pre size of agreedValue == AgreedValueLength()
-  \pre length of staticPrivateKey == StaticPrivateKeyLength()
-  \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
-  \pre length of staticOtherPublicKey == StaticPublicKeyLength()
-  \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
-  */
+  /// \brief Derive agreed value or shared secret
+  /// \param agreedValue the shared secret
+  /// \param staticPrivateKey your long term private key
+  /// \param ephemeralPrivateKey your ephemeral private key
+  /// \param staticOtherPublicKey couterparty's long term public key
+  /// \param ephemeralOtherPublicKey couterparty's ephemeral public key
+  /// \param validateStaticOtherPublicKey flag indicating validation
+  /// \return true upon success, false in case of failure
+  /// \details Agree() performs the authenticated key agreement. Agree()
+  ///  derives a shared secret from your private keys and couterparty's
+  ///  public keys. Each instance or run of the protocol should use a new
+  ///  ephemeral key pair.
+  /// \details The other's ephemeral public key will always be validated at
+  ///  Level 1 to ensure it is a point on the curve.
+  ///  <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
+  ///  static public key is validated. If you have previously validated the
+  ///  couterparty's static public key, then use
+  ///  <tt>validateStaticOtherPublicKey=false</tt> to save time.
+  /// \pre <tt>COUNTOF(agreedValue) == AgreedValueLength()</tt>
+  /// \pre <tt>COUNTOF(staticPrivateKey) == StaticPrivateKeyLength()</tt>
+  /// \pre <tt>COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength()</tt>
+  /// \pre <tt>COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength()</tt>
+  /// \pre <tt>COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength()</tt>
   bool Agree(byte *agreedValue,
     const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
     const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
     bool validateStaticOtherPublicKey=true) const
   {
-    byte *XX = NULLPTR, *YY = NULLPTR, *AA = NULLPTR, *BB = NULLPTR;
+    const byte *XX = NULLPTR, *YY = NULLPTR, *AA = NULLPTR, *BB = NULLPTR;
     size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
 
     // Depending on the role, this will hold either A's or B's static
@@ -135,6 +254,7 @@ public:
 
     try
     {
+      this->GetMaterial().DoQuickSanityCheck();
       const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
 
       if(m_role == RoleServer)
@@ -143,60 +263,43 @@ public:
         Element B = params.ExponentiateBase(b);
         params.EncodeElement(true, B, tt);
 
-        XX = const_cast<byte*>(ephemeralOtherPublicKey);
+        XX = ephemeralOtherPublicKey;
         xxs = EphemeralPublicKeyLength();
-        YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
+        YY = ephemeralPrivateKey + StaticPrivateKeyLength();
         yys = EphemeralPublicKeyLength();
-        AA = const_cast<byte*>(staticOtherPublicKey);
+        AA = staticOtherPublicKey;
         aas = StaticPublicKeyLength();
         BB = tt.BytePtr();
         bbs = tt.SizeInBytes();
       }
-      else if(m_role == RoleClient)
+      else
       {
         Integer a(staticPrivateKey, StaticPrivateKeyLength());
         Element A = params.ExponentiateBase(a);
         params.EncodeElement(true, A, tt);
 
-        XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
+        XX = ephemeralPrivateKey + StaticPrivateKeyLength();
         xxs = EphemeralPublicKeyLength();
-        YY = const_cast<byte*>(ephemeralOtherPublicKey);
+        YY = ephemeralOtherPublicKey;
         yys = EphemeralPublicKeyLength();
         AA = tt.BytePtr();
         aas = tt.SizeInBytes();
-        BB = const_cast<byte*>(staticOtherPublicKey);
+        BB = staticOtherPublicKey;
         bbs = StaticPublicKeyLength();
       }
-      else
-      {
-        CRYPTOPP_ASSERT(0);
-        return false;
-      }
-
-      // DecodeElement calls ValidateElement at level 1. Level 1 only calls
-      // VerifyPoint to ensure the element is in G*. If the other's PublicKey is
-      // requested to be validated, we manually call ValidateElement at level 3.
-      Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
-      if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULLPTR))
-        return false;
 
-      // DecodeElement calls ValidateElement at level 1. Level 1 only calls
-      // VerifyPoint to ensure the element is in G*. Crank it up.
-      Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
-      if(!params.ValidateElement(3, VV2, NULLPTR))
-        return false;
+      Element VV1 = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
+      Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, true);
 
       const Integer& q = params.GetSubgroupOrder();
       const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
-
-      Integer d, e;
       SecByteBlock dd(len), ee(len);
 
       Hash(NULLPTR, XX, xxs, YY, yys, AA, aas, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
-      d.Decode(dd.BytePtr(), dd.SizeInBytes());
+      Integer d(dd.BytePtr(), dd.SizeInBytes());
 
       Hash(NULLPTR, YY, yys, XX, xxs, AA, aas, BB, bbs, ee.BytePtr(), ee.SizeInBytes());
-      e.Decode(ee.BytePtr(), ee.SizeInBytes());
+      Integer e(ee.BytePtr(), ee.SizeInBytes());
 
       Element sigma;
       if(m_role == RoleServer)
@@ -232,6 +335,7 @@ public:
     }
     catch (DL_BadElement &)
     {
+      CRYPTOPP_ASSERT(0);
       return false;
     }
     return true;
@@ -250,9 +354,11 @@ protected:
 
     if(sigma)
     {
-      Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
-      SecByteBlock sbb(x.MinEncodedSize());
-      x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
+      //Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
+      //SecByteBlock sbb(x.MinEncodedSize());
+      //x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
+      SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
+      GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
       hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
     }
 
@@ -280,7 +386,7 @@ protected:
 private:
 
   // The paper uses Initiator and Recipient - make it classical.
-  enum KeyAgreementRole{ RoleServer = 1, RoleClient };
+  enum KeyAgreementRole { RoleServer = 1, RoleClient };
 
   DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
   const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
@@ -293,7 +399,7 @@ private:
 /// \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
 ///   <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
 ///   Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
-/// \sa FHMQV, MQV_Domain, HMQV_Domain, AuthenticatedKeyAgreementDomain
+/// \sa FHMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
 /// \since Crypto++ 5.6.4
 typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FHMQV;
 

+ 11 - 7
include/cryptlib/files.h

@@ -46,7 +46,7 @@ public:
 	FileStore(const char *filename) : m_stream(NULLPTR), m_space(NULLPTR), m_len(0), m_waiting(0)
 		{StoreInitialize(MakeParameters(Name::InputFileName(), filename ? filename : ""));}
 
-#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) || _MSC_VER >= 1400
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) || (CRYPTOPP_MSC_VERSION >= 1400)
 	/// \brief Construct a FileStore
 	/// \param filename the Unicode name of the file to open
 	/// \details On non-Windows OS, this function assumes that setlocale() has been called.
@@ -55,13 +55,17 @@ public:
 #endif
 
 	/// \brief Retrieves the internal stream
-	/// \returns the internal stream pointer
+	/// \return the internal stream pointer
 	std::istream* GetStream() {return m_stream;}
 
 	/// \brief Retrieves the internal stream
-	/// \returns the internal stream pointer
+	/// \return the internal stream pointer
 	const std::istream* GetStream() const {return m_stream;}
 
+	/// \brief Provides the number of bytes ready for retrieval
+	/// \return the number of bytes ready for retrieval
+	/// \details All retrieval functions return the actual number of bytes retrieved, which is
+	///  the lesser of the request number and  MaxRetrievable()
 	lword MaxRetrievable() const;
 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
@@ -105,7 +109,7 @@ public:
 	FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULLPTR, bool binary=true)
 		: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));}
 
-#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) || _MSC_VER >= 1400
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) || (CRYPTOPP_MSC_VERSION >= 1400)
 	/// \brief Construct a FileSource
 	/// \param filename the Unicode name of the file to open
 	/// \param pumpAll flag indicating if source data should be pumped to its attached transformation
@@ -117,7 +121,7 @@ public:
 #endif
 
 	/// \brief Retrieves the internal stream
-	/// \returns the internal stream pointer
+	/// \return the internal stream pointer
 	std::istream* GetStream() {return m_store.GetStream();}
 };
 
@@ -151,7 +155,7 @@ public:
 	FileSink(const char *filename, bool binary=true)
 		{IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)(Name::OutputBinaryMode(), binary));}
 
-#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || (CRYPTOPP_MSC_VERSION >= 1400)
 	/// \brief Construct a FileSink
 	/// \param filename the Unicode name of the file to open
 	/// \details On non-Windows OS, this function assumes that setlocale() has been called.
@@ -160,7 +164,7 @@ public:
 #endif
 
 	/// \brief Retrieves the internal stream
-	/// \returns the internal stream pointer
+	/// \return the internal stream pointer
 	std::ostream* GetStream() {return m_stream;}
 
 	void IsolatedInitialize(const NameValuePairs &parameters);

+ 233 - 137
include/cryptlib/filters.h

@@ -6,7 +6,7 @@
 #ifndef CRYPTOPP_FILTERS_H
 #define CRYPTOPP_FILTERS_H
 
-#include "cryptlib.h"
+#include "config.h"
 
 #if CRYPTOPP_MSC_VERSION
 # pragma warning(push)
@@ -25,13 +25,13 @@
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief Implementation of BufferedTransformation's attachment interface
-/// \details Filter is a cornerstone of the Pipeline trinitiy. Data flows from
-///   Sources, through Filters, and then terminates in Sinks. The difference
-///   between a Source and Filter is a Source \a pumps data, while a Filter does
-///   not. The difference between a Filter and a Sink is a Filter allows an
-///   attached transformation, while a Sink does not.
+/// \details Filter is a cornerstone of the Pipeline trinity. Data flows from
+///  Sources, through Filters, and then terminates in Sinks. The difference
+///  between a Source and Filter is a Source \a pumps data, while a Filter does
+///  not. The difference between a Filter and a Sink is a Filter allows an
+///  attached transformation, while a Sink does not.
 /// \details See the discussion of BufferedTransformation in cryptlib.h for
-///   more details.
+///  more details.
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable
 {
 public:
@@ -42,39 +42,49 @@ public:
 
 	/// \brief Construct a Filter
 	/// \param attachment an optional attached transformation
-	/// \details attachment can be \p NULL.
+	/// \details attachment can be NULL.
 	Filter(BufferedTransformation *attachment = NULLPTR);
 
 	/// \brief Determine if attachable
-	/// \returns \p true if the object allows attached transformations, \p false otherwise.
+	/// \return true if the object allows attached transformations, false otherwise.
 	/// \note Source and Filter offer attached transformations; while Sink does not.
 	bool Attachable() {return true;}
 
 	/// \brief Retrieve attached transformation
-	/// \returns pointer to a BufferedTransformation if there is an attached transformation, \p NULL otherwise.
+	/// \return pointer to a BufferedTransformation if there is an attached transformation, NULL otherwise.
 	BufferedTransformation *AttachedTransformation();
 
 	/// \brief Retrieve attached transformation
-	/// \returns pointer to a BufferedTransformation if there is an attached transformation, \p NULL otherwise.
+	/// \return pointer to a BufferedTransformation if there is an attached transformation, NULL otherwise.
 	const BufferedTransformation *AttachedTransformation() const;
 
 	/// \brief Replace an attached transformation
 	/// \param newAttachment an optional attached transformation
-	/// \details newAttachment can be a single filter, a chain of filters or \p NULL.
-	///    Pass \p NULL to remove an existing BufferedTransformation or chain of filters
+	/// \details newAttachment can be a single filter, a chain of filters or NULL.
+	///  Pass NULL to remove an existing BufferedTransformation or chain of filters
 	void Detach(BufferedTransformation *newAttachment = NULLPTR);
 
 	//@}
 
-	// See the documentation for BufferedTransformation in cryptlib.h
+	///	\name RETRIEVAL OF ONE MESSAGE
+	//@{
+
+	// BufferedTransformation in cryptlib.h
 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
 
-	// See the documentation for BufferedTransformation in cryptlib.h
+	//@}
+
+	///	\name SIGNALS
+	//@{
+
+	// BufferedTransformation in cryptlib.h
 	void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
 	bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
 	bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
 
+	//@}
+
 protected:
 	virtual BufferedTransformation * NewDefaultAttachment() const;
 	void Insert(Filter *nextFilter);	// insert filter after this one
@@ -91,7 +101,8 @@ protected:
 	/// \param messageEnd means how many filters to signal MessageEnd() to, including this one
 	/// \param blocking specifies whether the object should block when processing input
 	/// \param channel the channel to process the data
-	/// \returns the number of bytes that remain in the block (i.e., bytes not processed)
+	/// \return the number of bytes that remain to be processed (i.e., bytes not processed).
+	///  0 indicates all bytes were processed.
 	size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
 
 	/// \brief Output multiple bytes that may be modified by callee.
@@ -101,7 +112,8 @@ protected:
 	/// \param messageEnd means how many filters to signal MessageEnd() to, including this one
 	/// \param blocking specifies whether the object should block when processing input
 	/// \param channel the channel to process the data
-	/// \returns the number of bytes that remain in the block (i.e., bytes not processed)
+	/// \return the number of bytes that remain to be processed (i.e., bytes not processed).
+	///  0 indicates all bytes were processed.
 	size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
 
 	/// \brief Signals the end of messages to the object
@@ -109,9 +121,9 @@ protected:
 	/// \param propagation the number of attached transformations the  MessageEnd() signal should be passed
 	/// \param blocking specifies whether the object should block when processing input
 	/// \param channel the channel to process the data
-	/// \returns TODO
+	/// \return true is the MessageEnd signal was successful, false otherwise.
 	/// \details propagation count includes this object. Setting  propagation to <tt>1</tt> means this
-	///   object only. Setting propagation to <tt>-1</tt> means unlimited propagation.
+	///  object only. Setting propagation to <tt>-1</tt> means unlimited propagation.
 	bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
 
 	/// \brief Flush buffered input and/or output, with signal propagation
@@ -120,17 +132,17 @@ protected:
 	/// \param propagation the number of attached transformations the  Flush() signal should be passed
 	/// \param blocking specifies whether the object should block when processing input
 	/// \param channel the channel to process the data
-	/// \returns TODO
+	/// \return true is the Flush signal was successful, false otherwise.
 	/// \details propagation count includes this object. Setting  propagation to <tt>1</tt> means this
-	///   object only. Setting  propagation to <tt>-1</tt> means unlimited propagation.
+	///  object only. Setting  propagation to <tt>-1</tt> means unlimited propagation.
 	/// \note Hard flushes must be used with care. It means try to process and output everything, even if
-	///   there may not be enough data to complete the action. For example, hard flushing a  HexDecoder
-	///   would cause an error if you do it after inputing an odd number of hex encoded characters.
+	///  there may not be enough data to complete the action. For example, hard flushing a  HexDecoder
+	///  would cause an error if you do it after inputing an odd number of hex encoded characters.
 	/// \note For some types of filters, like  ZlibDecompressor, hard flushes can only
-	///   be done at "synchronization points". These synchronization points are positions in the data
-	///   stream that are created by hard flushes on the corresponding reverse filters, in this
-	///   example ZlibCompressor. This is useful when zlib compressed data is moved across a
-	///   network in packets and compression state is preserved across packets, as in the SSH2 protocol.
+	///  be done at "synchronization points". These synchronization points are positions in the data
+	///  stream that are created by hard flushes on the corresponding reverse filters, in this
+	///  example ZlibCompressor. This is useful when zlib compressed data is moved across a
+	///  network in packets and compression state is preserved across packets, as in the SSH2 protocol.
 	bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
 
 	/// \brief Marks the end of a series of messages, with signal propagation
@@ -138,11 +150,11 @@ protected:
 	/// \param propagation the number of attached transformations the  MessageSeriesEnd() signal should be passed
 	/// \param blocking specifies whether the object should block when processing input
 	/// \param channel the channel to process the data
-	/// \returns TODO
+	/// \return true is the MessageEnd signal was successful, false otherwise.
 	/// \details Each object that receives the signal will perform its processing, decrement
-	///    propagation, and then pass the signal on to attached transformations if the value is not 0.
+	///  propagation, and then pass the signal on to attached transformations if the value is not 0.
 	/// \details propagation count includes this object. Setting  propagation to <tt>1</tt> means this
-	///   object only. Setting  propagation to <tt>-1</tt> means unlimited propagation.
+	///  object only. Setting  propagation to <tt>-1</tt> means unlimited propagation.
 	/// \note There should be a MessageEnd() immediately before MessageSeriesEnd().
 	bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
 
@@ -166,12 +178,12 @@ struct CRYPTOPP_DLL FilterPutSpaceHelper
 	/// \param desiredSize preferred size of the allocation, in bytes
 	/// \param bufferSize actual size of the allocation, in bytes
 	/// \pre <tt>desiredSize >= minSize</tt> and <tt>bufferSize >= minSize</tt>.
-	/// \details \p bufferSize is an IN and OUT parameter. If HelpCreatePutSpace() returns a non-NULL value, then
-	///    bufferSize is valid and provides the size of the working space created for the caller.
+	/// \details bufferSize is an IN and OUT parameter. If HelpCreatePutSpace() returns a non-NULL value, then
+	///  bufferSize is valid and provides the size of the working space created for the caller.
 	/// \details Internally, HelpCreatePutSpace() calls \ref BufferedTransformation::ChannelCreatePutSpace
-	///   "ChannelCreatePutSpace()" using \p desiredSize. If the target returns \p desiredSize with a size less
-	///   than \p minSize (i.e., the request could not be fulfilled), then an internal SecByteBlock
-	///   called \p m_tempSpace is resized and used for the caller.
+	///  "ChannelCreatePutSpace()" using desiredSize. If the target returns desiredSize with a size less
+	///  than minSize (i.e., the request could not be fulfilled), then an internal SecByteBlock
+	///  called m_tempSpace is resized and used for the caller.
 	byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize)
 	{
 		CRYPTOPP_ASSERT(desiredSize >= minSize && bufferSize >= minSize);
@@ -194,7 +206,9 @@ struct CRYPTOPP_DLL FilterPutSpaceHelper
 	/// \param target the BufferedTransformation for the working space
 	/// \param channel channel for the working space
 	/// \param minSize minimum size of the allocation, in bytes
-	/// \details Internally, the overload calls HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize) using \p minSize for missing arguments.
+	/// \return pointer to the created space
+	/// \details Internally, the overload calls HelpCreatePutSpace() using minSize for missing arguments.
+	/// \details The filter will delete the space. The caller does not need to delete the space.
 	byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize)
 		{return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
 
@@ -203,17 +217,18 @@ struct CRYPTOPP_DLL FilterPutSpaceHelper
 	/// \param channel channel for the working space
 	/// \param minSize minimum size of the allocation, in bytes
 	/// \param bufferSize the actual size of the allocation, in bytes
-	/// \details Internally, the overload calls HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize) using \p minSize for missing arguments.
+	/// \details Internally, the overload calls HelpCreatePutSpace() using minSize for missing arguments.
+	/// \details The filter will delete the space. The caller does not need to delete the space.
 	byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize)
 		{return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
 
-	/// \brief Temporay working space
+	/// \brief Temporary working space
 	SecByteBlock m_tempSpace;
 };
 
 /// \brief Measure how many bytes and messages pass through the filter
 /// \details measure how many bytes and messages pass through the filter. The filter also serves as valve by
-///   maintaining a list of ranges to skip during processing.
+///  maintaining a list of ranges to skip during processing.
 class CRYPTOPP_DLL MeterFilter : public Bufferless<Filter>
 {
 public:
@@ -222,8 +237,8 @@ public:
 	/// \brief Construct a MeterFilter
 	/// \param attachment an optional attached transformation
 	/// \param transparent flag indicating if the filter should function transparently
-	/// \details \p attachment can be \p NULL. The filter is transparent by default. If the filter is
-	///   transparent, then PutMaybeModifiable() does not process a request and always returns 0.
+	/// \details attachment can be NULL. The filter is transparent by default. If the filter is
+	///  transparent, then PutMaybeModifiable() does not process a request and always returns 0.
 	MeterFilter(BufferedTransformation *attachment=NULLPTR, bool transparent=true)
 		: m_transparent(transparent), m_currentMessageBytes(0), m_totalBytes(0)
 		, m_currentSeriesMessages(0), m_totalMessages(0), m_totalMessageSeries(0)
@@ -239,25 +254,40 @@ public:
 	/// \param size the length of the range
 	/// \param sortNow flag indicating whether the range should be sorted
 	/// \details Internally, MeterFilter maitains a deque of ranges to skip. As messages are processed,
-	///   ranges of bytes are skipped according to the list of ranges.
+	///  ranges of bytes are skipped according to the list of ranges.
 	void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true);
 
 	/// \brief Resets the meter
 	/// \details ResetMeter() reinitializes the meter by setting counters to 0 and removing previous
-	///   skip ranges.
+	///  skip ranges.
 	void ResetMeter();
 
+	// BufferedTransformation in cryptlib.h
 	void IsolatedInitialize(const NameValuePairs &parameters)
 		{CRYPTOPP_UNUSED(parameters); ResetMeter();}
 
+	/// \brief Number of bytes in the current message
+	/// \return the number of bytes in the current message
 	lword GetCurrentMessageBytes() const {return m_currentMessageBytes;}
+
+	/// \brief Number of bytes processed by the filter
+	/// \return the number of bytes processed by the filter
 	lword GetTotalBytes() const {return m_totalBytes;}
+
+	/// \brief Message number in the series
+	/// \return the message number in the series
 	unsigned int GetCurrentSeriesMessages() const {return m_currentSeriesMessages;}
+
+	/// \brief Number of messages in the message series
+	/// \return the number of messages in the message series
 	unsigned int GetTotalMessages() const {return m_totalMessages;}
+
+	/// \brief Number of messages processed by the filter
+	/// \return the number of messages processed by the filter
 	unsigned int GetTotalMessageSeries() const {return m_totalMessageSeries;}
 
-	byte * CreatePutSpace(size_t &size)
-		{return AttachedTransformation()->CreatePutSpace(size);}
+	// BufferedTransformation in cryptlib.h
+	byte * CreatePutSpace(size_t &size) {return AttachedTransformation()->CreatePutSpace(size);}
 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
 	size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking);
 	bool IsolatedMessageSeriesEnd(bool blocking);
@@ -304,10 +334,10 @@ public:
 
 /// \brief Divides an input stream into discrete blocks
 /// \details FilterWithBufferedInput divides the input stream into a first block, a number of
-///   middle blocks, and a last block. First and last blocks are optional, and middle blocks may
-///   be a stream instead (i.e. <tt>blockSize == 1</tt>).
+///  middle blocks, and a last block. First and last blocks are optional, and middle blocks may
+///  be a stream instead (i.e. <tt>blockSize == 1</tt>).
 /// \sa AuthenticatedEncryptionFilter, AuthenticatedDecryptionFilter, HashVerificationFilter,
-///   SignatureVerificationFilter, StreamTransformationFilter
+///  SignatureVerificationFilter, StreamTransformationFilter
 class CRYPTOPP_DLL FilterWithBufferedInput : public Filter
 {
 public:
@@ -322,7 +352,7 @@ public:
 	/// \param blockSize the size of middle blocks
 	/// \param lastSize the size of the last block
 	/// \param attachment an attached transformation
-	/// \details \p firstSize and \p lastSize may be 0. \p blockSize must be at least 1.
+	/// \details firstSize and lastSize may be 0. blockSize must be at least 1.
 	FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment);
 
 	void IsolatedInitialize(const NameValuePairs &parameters);
@@ -339,13 +369,14 @@ public:
 	/// \brief Flushes data buffered by this object, without signal propagation
 	/// \param hardFlush indicates whether all data should be flushed
 	/// \param blocking specifies whether the object should block when processing input
+	/// \return true if the Flush was successful, false otherwise
 	/// \details IsolatedFlush() calls ForceNextPut() if hardFlush is true
 	/// \note  hardFlush must be used with care
 	bool IsolatedFlush(bool hardFlush, bool blocking);
 
 	/// \brief Flushes data buffered by this object
 	/// \details The input buffer may contain more than blockSize bytes if <tt>lastSize != 0</tt>.
-	///   ForceNextPut() forces a call to NextPut() if this is the case.
+	///  ForceNextPut() forces a call to NextPut() if this is the case.
 	void ForceNextPut();
 
 protected:
@@ -375,7 +406,7 @@ protected:
 	/// \param inString the input byte buffer
 	/// \param length the size of the input buffer, in bytes
 	/// \details LastPut() processes the last block of data and signals attached filters to do the same.
-	///   LastPut() is always called. The pseudo algorithm for the logic is:
+	///  LastPut() is always called. The pseudo algorithm for the logic is:
 	/// <pre>
 	///     if totalLength < firstSize then length == totalLength
 	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
@@ -421,8 +452,8 @@ protected:
 
 /// \brief A filter that buffers input using a ByteQueue
 /// \details FilterWithInputQueue will buffer input using a ByteQueue. When the filter receives
-///   a \ref BufferedTransformation::MessageEnd() "MessageEnd()" signal it will pass the data
-///   on to its attached transformation.
+///  a \ref BufferedTransformation::MessageEnd() "MessageEnd()" signal it will pass the data
+///  on to its attached transformation.
 class CRYPTOPP_DLL FilterWithInputQueue : public Filter
 {
 public:
@@ -462,10 +493,10 @@ struct BlockPaddingSchemeDef
 	/// \enum BlockPaddingScheme
 	/// \brief Padding schemes used for block ciphers.
 	/// \details DEFAULT_PADDING means PKCS_PADDING if <tt>cipher.MandatoryBlockSize() > 1 &&
-	///   cipher.MinLastBlockSize() == 0</tt>, which holds for ECB or CBC mode. Otherwise,
-	///   NO_PADDING for modes like OFB, CFB, CTR, CBC-CTS.
+	///  cipher.MinLastBlockSize() == 0</tt>, which holds for ECB or CBC mode. Otherwise,
+	///  NO_PADDING for modes like OFB, CFB, CTR, CBC-CTS.
 	/// \sa <A HREF="http://www.weidai.com/scan-mirror/csp.html">Block Cipher Padding</A> for
-	///   additional details.
+	///  additional details.
 	/// \since Crypto++ 5.0
 	enum BlockPaddingScheme {
 		/// \brief No padding added to a block
@@ -474,7 +505,7 @@ struct BlockPaddingSchemeDef
 		/// \brief 0's padding added to a block
 		/// \since Crypto++ 5.0
 		ZEROS_PADDING,
-		/// \brief PKCS #5 padding added to a block
+		/// \brief PKCS padding added to a block
 		/// \since Crypto++ 5.0
 		PKCS_PADDING,
 		/// \brief 1 and 0's padding added to a block
@@ -482,7 +513,7 @@ struct BlockPaddingSchemeDef
 		ONE_AND_ZEROS_PADDING,
 		/// \brief W3C padding added to a block
 		/// \sa <A HREF="http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html">XML
-		///   Encryption Syntax and Processing</A>
+		///  Encryption Syntax and Processing</A>
 		/// \since Crypto++ 6.0
 		W3C_PADDING,
 		/// \brief Default padding scheme
@@ -493,9 +524,9 @@ struct BlockPaddingSchemeDef
 
 /// \brief Filter wrapper for StreamTransformation
 /// \details StreamTransformationFilter() is a filter wrapper for StreamTransformation(). It is used when
-///   pipelining data for stream ciphers and confidentiality-only block ciphers. The filter will optionally
-///   handle padding and unpadding when needed. If you are using an authenticated encryption mode of operation,
-///   then use AuthenticatedEncryptionFilter() and AuthenticatedDecryptionFilter()
+///  pipelining data for stream ciphers and confidentiality-only block ciphers. The filter will optionally
+///  handle padding and unpadding when needed. If you are using an authenticated encryption mode of operation,
+///  then use AuthenticatedEncryptionFilter() and AuthenticatedDecryptionFilter()
 /// \since Crypto++ 5.0
 class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper
 {
@@ -506,10 +537,10 @@ public:
 	/// \param c reference to a StreamTransformation
 	/// \param attachment an optional attached transformation
 	/// \param padding the \ref BlockPaddingSchemeDef "padding scheme"
-	/// \details This contructor creates a StreamTransformationFilter() for stream ciphers and
-	///   confidentiality-only block cipher modes of operation. If you are using an authenticated
-	///   encryption mode of operation, then use either AuthenticatedEncryptionFilter() or
-	///   AuthenticatedDecryptionFilter().
+	/// \details This constructor creates a StreamTransformationFilter() for stream ciphers and
+	///  confidentiality-only block cipher modes of operation. If you are using an authenticated
+	///  encryption mode of operation, then use either AuthenticatedEncryptionFilter() or
+	///  AuthenticatedDecryptionFilter().
 	/// \sa AuthenticatedEncryptionFilter() and AuthenticatedDecryptionFilter()
 	StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULLPTR, BlockPaddingScheme padding = DEFAULT_PADDING);
 
@@ -526,7 +557,7 @@ protected:
 	/// \param padding the \ref BlockPaddingSchemeDef "padding scheme"
 	/// \param authenticated flag indicating whether the filter should allow authenticated encryption schemes
 	/// \details This constructor is used for authenticated encryption mode of operation and by
-	///   AuthenticatedEncryptionFilter() and AuthenticatedDecryptionFilter().
+	///  AuthenticatedEncryptionFilter() and AuthenticatedDecryptionFilter().
 	StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool authenticated);
 
 	void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
@@ -593,19 +624,19 @@ public:
 	/// \brief Flags controlling filter behavior.
 	/// \details The flags are a bitmask and can be OR'd together.
 	enum Flags {
-		/// \brief Indicates the hash is at the end of the message (i.e., concatenation of message+hash)
+		/// \brief The hash is at the end of the message (i.e., concatenation of message+hash)
 		HASH_AT_END=0,
-		/// \brief Indicates the hash is at the beginning of the message (i.e., concatenation of hash+message)
+		/// \brief The hash is at the beginning of the message (i.e., concatenation of hash+message)
 		HASH_AT_BEGIN=1,
-		/// \brief Indicates the message should be passed to an attached transformation
+		/// \brief The message should be passed to an attached transformation
 		PUT_MESSAGE=2,
-		/// \brief Indicates the hash should be passed to an attached transformation
+		/// \brief The hash should be passed to an attached transformation
 		PUT_HASH=4,
-		/// \brief Indicates the result of the verification should be passed to an attached transformation
+		/// \brief The result of the verification should be passed to an attached transformation
 		PUT_RESULT=8,
-		/// \brief Indicates the filter should throw a HashVerificationFailed if a failure is encountered
+		/// \brief The filter should throw a HashVerificationFailed if a failure is encountered
 		THROW_EXCEPTION=16,
-		/// \brief Default flags using \p HASH_AT_BEGIN and \p PUT_RESULT
+		/// \brief Default flags using HASH_AT_BEGIN and PUT_RESULT
 		DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT
 	};
 
@@ -637,9 +668,16 @@ private:
 };
 
 /// \brief Filter wrapper for encrypting with AuthenticatedSymmetricCipher
-/// \details AuthenticatedEncryptionFilter() is a wrapper for encrypting with AuthenticatedSymmetricCipher(),
-///   optionally handling padding/unpadding when needed.
-/// \sa AuthenticatedDecryptionFilter, EAX, CCM, GCM, AuthenticatedSymmetricCipher
+/// \details AuthenticatedEncryptionFilter() is a wrapper for encrypting with
+///  AuthenticatedSymmetricCipher(), optionally handling padding/unpadding when needed.
+/// \details AuthenticatedDecryptionFilter() for Crypto++ 8.2 and earlier
+///  had a bug where a FileSource() would cause an exception, but a StringSource()
+///  was OK. Also see <A HREF=
+///  "https://github.com/weidai11/cryptopp/issues/817">Issue 817</A> and <A HREF=
+///  "https://github.com/weidai11/cryptopp/commit/ff110c6e183e">Commit ff110c6e183e</A>.
+/// \sa AuthenticatedSymmetricCipher, AuthenticatedDecryptionFilter, EAX, CCM, GCM,
+///  and <A HREF="https://www.cryptopp.com/wiki/AadSource">AadSource</A> on the
+///  Crypto++ wiki.
 /// \since Crypto++ 5.6.0
 class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter
 {
@@ -665,7 +703,7 @@ public:
 	/// \param inString the input byte buffer
 	/// \param length the size of the input buffer, in bytes
 	/// \details LastPut() processes the last block of data and signals attached filters to do the same.
-	///   LastPut() is always called. The pseudo algorithm for the logic is:
+	///  LastPut() is always called. The pseudo algorithm for the logic is:
 	/// <pre>
 	///     if totalLength < firstSize then length == totalLength
 	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
@@ -678,9 +716,17 @@ protected:
 };
 
 /// \brief Filter wrapper for decrypting with AuthenticatedSymmetricCipher
-/// \details AuthenticatedDecryptionFilter() is a wrapper for decrypting with AuthenticatedSymmetricCipher(),
-///   optionally handling padding/unpadding when needed.
-/// \sa AuthenticatedEncryptionFilter, EAX, CCM, GCM, AuthenticatedSymmetricCipher
+/// \details AuthenticatedDecryptionFilter() is a wrapper for decrypting with
+///  AuthenticatedSymmetricCipher(), optionally handling padding/unpadding when
+///  needed.
+/// \details AuthenticatedDecryptionFilter() for Crypto++ 8.2 and earlier
+///  had a bug where a FileSource() would cause an exception, but a StringSource()
+///  was OK. Also see <A HREF=
+///  "https://github.com/weidai11/cryptopp/issues/817">Issue 817</A> and <A HREF=
+///  "https://github.com/weidai11/cryptopp/commit/ff110c6e183e">Commit ff110c6e183e</A>.
+/// \sa AuthenticatedSymmetricCipher, AuthenticatedEncryptionFilter, EAX, CCM, GCM,
+///  and <A HREF="https://www.cryptopp.com/wiki/AadSource">AadSource</A> on the
+///  Crypto++ wiki.
 /// \since Crypto++ 5.6.0
 class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef
 {
@@ -689,13 +735,13 @@ public:
 	/// \brief Flags controlling filter behavior.
 	/// \details The flags are a bitmask and can be OR'd together.
 	enum Flags {
-		/// \brief Indicates the MAC is at the end of the message (i.e., concatenation of message+mac)
+		/// \brief The MAC is at the end of the message (i.e., concatenation of message+mac)
 		MAC_AT_END=0,
-		/// \brief Indicates the MAC is at the beginning of the message (i.e., concatenation of mac+message)
+		/// \brief The MAC is at the beginning of the message (i.e., concatenation of mac+message)
 		MAC_AT_BEGIN=1,
-		/// \brief Indicates the filter should throw a HashVerificationFailed if a failure is encountered
+		/// \brief The filter should throw a HashVerificationFailed if a failure is encountered
 		THROW_EXCEPTION=16,
-		/// \brief Default flags using \p THROW_EXCEPTION
+		/// \brief Default flags using THROW_EXCEPTION
 		DEFAULT_FLAGS = THROW_EXCEPTION
 	};
 
@@ -715,6 +761,10 @@ public:
 	std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();}
 	byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
 	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+	size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
+		{ return ChannelPut2(channel, begin, length, messageEnd, blocking); }
+	/// \brief Get verifier result
+	/// \return true if the digest on the previosus message was valid, false otherwise
 	bool GetLastResult() const {return m_hashVerifier.GetLastResult();}
 
 protected:
@@ -726,7 +776,7 @@ protected:
 	/// \param inString the input byte buffer
 	/// \param length the size of the input buffer, in bytes
 	/// \details LastPut() processes the last block of data and signals attached filters to do the same.
-	///   LastPut() is always called. The pseudo algorithm for the logic is:
+	///  LastPut() is always called. The pseudo algorithm for the logic is:
 	/// <pre>
 	///     if totalLength < firstSize then length == totalLength
 	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
@@ -784,19 +834,19 @@ public:
 	/// \brief Flags controlling filter behavior.
 	/// \details The flags are a bitmask and can be OR'd together.
 	enum Flags {
-		/// \brief Indicates the signature is at the end of the message (i.e., concatenation of message+signature)
+		/// \brief The signature is at the end of the message (i.e., concatenation of message+signature)
 		SIGNATURE_AT_END=0,
-		/// \brief Indicates the signature is at the beginning of the message (i.e., concatenation of signature+message)
+		/// \brief The signature is at the beginning of the message (i.e., concatenation of signature+message)
 		SIGNATURE_AT_BEGIN=1,
-		/// \brief Indicates the message should be passed to an attached transformation
+		/// \brief The message should be passed to an attached transformation
 		PUT_MESSAGE=2,
-		/// \brief Indicates the signature should be passed to an attached transformation
+		/// \brief The signature should be passed to an attached transformation
 		PUT_SIGNATURE=4,
-		/// \brief Indicates the result of the verification should be passed to an attached transformation
+		/// \brief The result of the verification should be passed to an attached transformation
 		PUT_RESULT=8,
-		/// \brief Indicates the filter should throw a HashVerificationFailed if a failure is encountered
+		/// \brief The filter should throw a HashVerificationFailed if a failure is encountered
 		THROW_EXCEPTION=16,
-		/// \brief Default flags using \p SIGNATURE_AT_BEGIN and \p PUT_RESULT
+		/// \brief Default flags using SIGNATURE_AT_BEGIN and PUT_RESULT
 		DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT
 	};
 
@@ -811,7 +861,7 @@ public:
 	std::string AlgorithmName() const {return m_verifier.AlgorithmName();}
 
 	/// \brief Retrieves the result of the last verification
-	/// \returns true if the signature on the previosus message was valid, false otherwise
+	/// \return true if the signature on the previosus message was valid, false otherwise
 	bool GetLastResult() const {return m_verified;}
 
 protected:
@@ -865,12 +915,24 @@ public:
 	/// \brief Stop redirecting input
 	void StopRedirection() {m_target = NULLPTR;}
 
-	Behavior GetBehavior() {return (Behavior) m_behavior;}
+	/// \brief Retrieve signal propagation behavior
+	/// \return the current signal propagation behavior
+	Behavior GetBehavior() {return static_cast<Behavior>(m_behavior);}
+	/// \brief Set signal propagation behavior
+	/// \param behavior the new signal propagation behavior
 	void SetBehavior(Behavior behavior) {m_behavior=behavior;}
+	/// \brief Retrieve signal propagation behavior
+	/// \return true if the Redirector passes signals, false otherwise.
 	bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;}
-	void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; }
+	/// \brief Set signal propagation behavior
+	/// \param pass flag indicating if the Redirector should pass signals
+	void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~static_cast<word32>(PASS_SIGNALS); }
+	/// \brief Retrieve signal propagation behavior
+	/// \return true if the Redirector passes wait objects, false otherwise.
 	bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;}
-	void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; }
+	/// \brief Set signal propagation behavior
+	/// \param pass flag indicating if the Redirector should pass wait objects
+	void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~static_cast<word32>(PASS_WAIT_OBJECTS); }
 
 	bool CanModifyInput() const
 		{return m_target ? m_target->CanModifyInput() : false;}
@@ -936,7 +998,7 @@ public:
 	OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
 
 	/// \brief Retrieve passSignal flag
-	/// \returns flag indicating if signals should be passed
+	/// \return flag indicating if signals should be passed
 	bool GetPassSignal() const {return m_passSignal;}
 	/// \brief Set passSignal flag
 	/// \param passSignal flag indicating if signals should be passed
@@ -1015,7 +1077,7 @@ public:
 	/// \param inString the input byte buffer
 	/// \param length the size of the input buffer, in bytes
 	/// \details LastPut() processes the last block of data and signals attached filters to do the same.
-	///   LastPut() is always called. The pseudo algorithm for the logic is:
+	///  LastPut() is always called. The pseudo algorithm for the logic is:
 	/// <pre>
 	///     if totalLength < firstSize then length == totalLength
 	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
@@ -1027,7 +1089,7 @@ public:
 
 /// \brief Filter wrapper for PK_Encryptor
 /// \details PK_DecryptorFilter is a proxy for the filter created by PK_Encryptor::CreateEncryptionFilter.
-///   This class provides symmetry with VerifierFilter.
+///  This class provides symmetry with VerifierFilter.
 /// \since Crypto++ 5.0
 class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter
 {
@@ -1042,7 +1104,7 @@ public:
 
 /// \brief Filter wrapper for PK_Decryptor
 /// \details PK_DecryptorFilter is a proxy for the filter created by PK_Decryptor::CreateDecryptionFilter.
-///   This class provides symmetry with SignerFilter.
+///  This class provides symmetry with SignerFilter.
 /// \since Crypto++ 5.0
 class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter
 {
@@ -1063,12 +1125,13 @@ template <class T>
 class StringSinkTemplate : public Bufferless<Sink>
 {
 public:
+	typedef typename T::value_type value_type;
 	virtual ~StringSinkTemplate() {}
 
 	/// \brief Construct a StringSinkTemplate
-	/// \param output std::basic_string<char> type
+	/// \param output std::basic_string<char> or std::vector<byte> type
 	StringSinkTemplate(T &output)
-		: m_output(&output) {CRYPTOPP_ASSERT(sizeof(output[0])==1);}
+		: m_output(&output) {CRYPTOPP_ASSERT(sizeof(value_type)==1);}
 
 	void IsolatedInitialize(const NameValuePairs &parameters)
 		{if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
@@ -1076,14 +1139,12 @@ public:
 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
 	{
 		CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
-		typedef typename T::traits_type::char_type char_type;
-
 		if (length > 0)
 		{
 			typename T::size_type size = m_output->size();
 			if (length < size && size + length > m_output->capacity())
 				m_output->reserve(2*size);
-			m_output->append((const char_type *)inString, (const char_type *)inString+length);
+			m_output->insert(m_output->end(), (const value_type *)inString, (const value_type *)inString+length);
 		}
 		return 0;
 	}
@@ -1096,9 +1157,15 @@ private:
 /// \details StringSink is a typedef for StringSinkTemplate<std::string>.
 /// \sa ArraySink, ArrayXorSink
 /// \since Crypto++ 4.0
-DOCUMENTED_TYPEDEF(StringSinkTemplate<std::string>, StringSink)
+DOCUMENTED_TYPEDEF(StringSinkTemplate<std::string>, StringSink);
 CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate<std::string>;
 
+/// \brief Append input to a std::vector<byte> object
+/// \details VectorSink is a typedef for StringSinkTemplate<std::vector<byte> >.
+/// \since Crypto++ 8.0
+DOCUMENTED_TYPEDEF(StringSinkTemplate<std::vector<byte> >, VectorSink);
+CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate<std::vector<byte> >;
+
 /// \brief Incorporates input into RNG as additional entropy
 /// \since Crypto++ 4.0
 class RandomNumberSink : public Bufferless<Sink>
@@ -1124,9 +1191,9 @@ private:
 
 /// \brief Copy input to a memory buffer
 /// \details ArraySink wraps a fixed size buffer. The buffer is full once Put returns non-0.
-///   When used in a pipleline, ArraySink silently discards input if the buffer is full.
-///   AvailableSize() can be used to determine how much space remains in the buffer.
-///   TotalPutLength() can be used to determine how many bytes were processed.
+///  When used in a pipeline, ArraySink silently discards input if the buffer is full.
+///  AvailableSize() can be used to determine how much space remains in the buffer.
+///  TotalPutLength() can be used to determine how many bytes were processed.
 /// \sa StringSink, ArrayXorSink
 /// \since Crypto++ 4.0
 class CRYPTOPP_DLL ArraySink : public Bufferless<Sink>
@@ -1147,11 +1214,11 @@ public:
 		: m_buf(buf), m_size(size), m_total(0) {}
 
 	/// \brief Provides the size remaining in the Sink
-	/// \returns size remaining in the Sink, in bytes
+	/// \return size remaining in the Sink, in bytes
 	size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);}
 
 	/// \brief Provides the number of bytes written to the Sink
-	/// \returns number of bytes written to the Sink, in bytes
+	/// \return number of bytes written to the Sink, in bytes
 	lword TotalPutLength() {return m_total;}
 
 	void IsolatedInitialize(const NameValuePairs &parameters);
@@ -1166,9 +1233,9 @@ protected:
 
 /// \brief Xor input to a memory buffer
 /// \details ArrayXorSink wraps a fixed size buffer. The buffer is full once Put returns non-0.
-///   When used in a pipleline, ArrayXorSink silently discards input if the buffer is full.
-///   AvailableSize() can be used to determine how much space remains in the buffer.
-///   TotalPutLength() can be used to determine how many bytes were processed.
+///  When used in a pipeline, ArrayXorSink silently discards input if the buffer is full.
+///  AvailableSize() can be used to determine how much space remains in the buffer.
+///  TotalPutLength() can be used to determine how many bytes were processed.
 /// \sa StringSink, ArraySink
 /// \since Crypto++ 4.0
 class CRYPTOPP_DLL ArrayXorSink : public ArraySink
@@ -1266,12 +1333,12 @@ private:
 
 /// \brief Implementation of BufferedTransformation's attachment interface
 /// \details Source is a cornerstone of the Pipeline trinitiy. Data flows from
-///   Sources, through Filters, and then terminates in Sinks. The difference
-///   between a Source and Filter is a Source \a pumps data, while a Filter does
-///   not. The difference between a Filter and a Sink is a Filter allows an
-///   attached transformation, while a Sink does not.
+///  Sources, through Filters, and then terminates in Sinks. The difference
+///  between a Source and Filter is a Source \a pumps data, while a Filter does
+///  not. The difference between a Filter and a Sink is a Filter allows an
+///  attached transformation, while a Sink does not.
 /// \details See the discussion of BufferedTransformation in cryptlib.h for
-///   more details.
+///  more details.
 /// \sa Store and SourceTemplate
 /// \since Crypto++ 1.0
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting<Filter>
@@ -1288,48 +1355,59 @@ public:
 	//@{
 
 	/// \brief Pump data to attached transformation
-	/// \param pumpMax the maximpum number of bytes to pump
-	/// \returns the number of bytes that remain in the block (i.e., bytes not processed)
+	/// \param pumpMax the maximum number of bytes to pump
+	/// \return the number of bytes that remain to be processed (i.e., bytes not processed).
+	///  0 indicates all bytes were processed.
 	/// \details Internally, Pump() calls Pump2().
-	/// \note pumpMax is a \p lword, which is a 64-bit value that typically uses \p LWORD_MAX. The default
-	///   argument is a \p size_t that uses \p SIZE_MAX, and it can be 32-bits or 64-bits.
-	lword Pump(lword pumpMax=(size_t)SIZE_MAX)
+	/// \note pumpMax is a <tt>lword</tt>, which is a 64-bit value that typically uses
+	///  <tt>LWORD_MAX</tt>. The default argument is <tt>SIZE_MAX</tt>, and it can be
+	///  32-bits or 64-bits.
+	/// \sa Pump2, PumpAll, AnyRetrievable, MaxRetrievable
+	lword Pump(lword pumpMax=SIZE_MAX)
 		{Pump2(pumpMax); return pumpMax;}
 
 	/// \brief Pump messages to attached transformation
-	/// \param count the maximpum number of messages to pump
-	/// \returns TODO
+	/// \param count the maximum number of messages to pump
+	/// \return TODO
 	/// \details Internally, PumpMessages() calls PumpMessages2().
 	unsigned int PumpMessages(unsigned int count=UINT_MAX)
 		{PumpMessages2(count); return count;}
 
 	/// \brief Pump all data to attached transformation
-	/// \details Internally, PumpAll() calls PumpAll2().
+	/// \details Pumps all data to the attached transformation and signal the end of the current
+	///  message. To avoid the MessageEnd() signal call \ref Pump "Pump(LWORD_MAX)" or \ref Pump2
+	///  "Pump2(LWORD_MAX, bool)".
+	/// \details Internally, PumpAll() calls PumpAll2(), which calls PumpMessages().
+	/// \sa Pump, Pump2, AnyRetrievable, MaxRetrievable
 	void PumpAll()
 		{PumpAll2();}
 
 	/// \brief Pump data to attached transformation
-	/// \param byteCount the maximpum number of bytes to pump
+	/// \param byteCount the maximum number of bytes to pump
 	/// \param blocking specifies whether the object should block when processing input
-	/// \returns the number of bytes that remain in the block (i.e., bytes not processed)
+	/// \return the number of bytes that remain to be processed (i.e., bytes not processed).
+	///  0 indicates all bytes were processed.
 	/// \details byteCount is an \a IN and \a OUT parameter. When the call is made, byteCount is the
-	///   requested size of the pump. When the call returns, byteCount is the number of bytes that
-	///   were pumped.
+	///  requested size of the pump. When the call returns, byteCount is the number of bytes that
+	///  were pumped.
+	/// \sa Pump, PumpAll, AnyRetrievable, MaxRetrievable
 	virtual size_t Pump2(lword &byteCount, bool blocking=true) =0;
 
 	/// \brief Pump messages to attached transformation
-	/// \param messageCount the maximpum number of messages to pump
+	/// \param messageCount the maximum number of messages to pump
 	/// \param blocking specifies whether the object should block when processing input
 	/// \details messageCount is an IN and OUT parameter.
 	virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
 
 	/// \brief Pump all data to attached transformation
 	/// \param blocking specifies whether the object should block when processing input
-	/// \returns the number of bytes that remain in the block (i.e., bytes not processed)
+	/// \return the number of bytes that remain to be processed (i.e., bytes not processed).
+	///  0 indicates all bytes were processed.
+	/// \sa Pump, Pump2, AnyRetrievable, MaxRetrievable
 	virtual size_t PumpAll2(bool blocking=true);
 
 	/// \brief Determines if the Source is exhausted
-	/// \returns true if the source has been exhausted
+	/// \return true if the source has been exhausted
 	virtual bool SourceExhausted() const =0;
 
 	//@}
@@ -1354,7 +1432,7 @@ public:
 
 	/// \brief Construct a SourceTemplate
 	/// \param attachment an attached transformation
-	SourceTemplate<T>(BufferedTransformation *attachment)
+	SourceTemplate(BufferedTransformation *attachment)
 		: Source(attachment) {}
 	void IsolatedInitialize(const NameValuePairs &parameters)
 		{m_store.IsolatedInitialize(parameters);}
@@ -1410,9 +1488,27 @@ public:
 
 /// \brief Pointer-based implementation of the Source interface
 /// \details ArraySource is a typedef for StringSource. Use the third constructor for an array source.
-///   The third constructor takes a pointer and length.
+///  The third constructor takes a pointer and length.
 /// \since Crypto++ 5.6.0
-DOCUMENTED_TYPEDEF(StringSource, ArraySource)
+DOCUMENTED_TYPEDEF(StringSource, ArraySource);
+
+/// \brief std::vector-based implementation of the Source interface
+/// \since Crypto++ 8.0
+class CRYPTOPP_DLL VectorSource : public SourceTemplate<StringStore>
+{
+public:
+	/// \brief Construct a VectorSource
+	/// \param attachment an optional attached transformation
+	VectorSource(BufferedTransformation *attachment = NULLPTR)
+		: SourceTemplate<StringStore>(attachment) {}
+
+	/// \brief Construct a VectorSource
+	/// \param vec vector of bytes
+	/// \param pumpAll flag indicating if source data should be pumped to its attached transformation
+	/// \param attachment an optional attached transformation
+	VectorSource(const std::vector<byte> &vec, bool pumpAll, BufferedTransformation *attachment = NULLPTR)
+		: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(vec)));}
+};
 
 /// \brief RNG-based implementation of Source interface
 /// \since Crypto++ 4.0

+ 8 - 8
include/cryptlib/fips140.h

@@ -17,7 +17,7 @@
 NAMESPACE_BEGIN(CryptoPP)
 
 /// Exception thrown when a crypto algorithm is used after a self test fails
-/// \details The self tests for an algorithm are performed by Algortihm class
+/// \details The self tests for an algorithm are performed by Algorithm class
 ///   when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined.
 class CRYPTOPP_DLL SelfTestFailure : public Exception
 {
@@ -26,7 +26,7 @@ public:
 };
 
 /// \brief Determines whether the library provides FIPS validated cryptography
-/// \returns true if FIPS 140-2 validated features were enabled at compile time.
+/// \return true if FIPS 140-2 validated features were enabled at compile time.
 /// \details true if FIPS 140-2 validated features were enabled at compile time,
 ///   false otherwise.
 /// \note FIPS mode is enabled at compile time. A program or other module cannot
@@ -51,7 +51,7 @@ enum PowerUpSelfTestStatus {
 /// \param expectedModuleMac the expected MAC of the components protected by the integrity check
 /// \details Performs the power-up self test, and sets the self test status to
 ///   POWER_UP_SELF_TEST_PASSED or POWER_UP_SELF_TEST_FAILED.
-/// \details The self tests for an algorithm are performed by the Algortihm class
+/// \details The self tests for an algorithm are performed by the Algorithm class
 ///   when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined.
 CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac);
 
@@ -59,7 +59,7 @@ CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, con
 /// \details Performs the power-up self test using the filename of this DLL and the
 ///   embedded module MAC, and sets the self test status to POWER_UP_SELF_TEST_PASSED or
 ///   POWER_UP_SELF_TEST_FAILED.
-/// \details The self tests for an algorithm are performed by the Algortihm class
+/// \details The self tests for an algorithm are performed by the Algorithm class
 ///   when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined.
 CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest();
 
@@ -68,7 +68,7 @@ CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest();
 CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure();
 
 /// \brief Provides the current power-up self test status
-/// \returns the current power-up self test status
+/// \return the current power-up self test status
 CRYPTOPP_DLL PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus();
 
 #ifndef CRYPTOPP_DOXYGEN_PROCESSING
@@ -76,15 +76,15 @@ typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)();
 #endif
 
 /// \brief Class object that calculates the MAC on the module
-/// \returns the MAC for the module
+/// \return the MAC for the module
 CRYPTOPP_DLL MessageAuthenticationCode * CRYPTOPP_API NewIntegrityCheckingMAC();
 
 /// \brief Verifies the MAC on the module
 /// \param moduleFilename the fully qualified name of the module
 /// \param expectedModuleMac the expected MAC of the components protected by the integrity check
 /// \param pActualMac the actual MAC of the components calculated by the integrity check
-/// \param pMacFileLocation the offest of the MAC in the PE/PE+ module
-/// \returns true if the MAC is valid, false otherwise
+/// \param pMacFileLocation the offset of the MAC in the PE/PE+ module
+/// \return true if the MAC is valid, false otherwise
 CRYPTOPP_DLL bool CRYPTOPP_API IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac = NULLPTR, unsigned long *pMacFileLocation = NULLPTR);
 
 #ifndef CRYPTOPP_DOXYGEN_PROCESSING

+ 3 - 21
include/cryptlib/fltrimpl.h

@@ -1,16 +1,6 @@
 #ifndef CRYPTOPP_FLTRIMPL_H
 #define CRYPTOPP_FLTRIMPL_H
 
-#if CRYPTOPP_MSC_VERSION
-# pragma warning(push)
-# pragma warning(disable: 4100)
-#endif
-
-#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-value"
-#endif
-
 #define FILTER_BEGIN	\
 	switch (m_continueAt)	\
 	{	\
@@ -38,7 +28,7 @@
 #define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel)	\
 	{\
 	case site:	\
-	statement;	\
+	(void) statement;	\
 	if (Output(site, output, length, messageEnd, blocking, channel))	\
 		return STDMAX(size_t(1), length-m_inputPosition);\
 	}
@@ -56,7 +46,7 @@
 	{\
 	/* fall through */ \
 	case site:	\
-	statement;	\
+	(void) statement;	\
 	if (OutputModifiable(site, output, length, messageEnd, blocking))	\
 		return STDMAX(size_t(1), length-m_inputPosition);\
 	}
@@ -68,7 +58,7 @@
 	{\
 	/* fall through */ \
 	case site:	\
-	statement;	\
+	(void) statement;	\
 	if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking))	\
 		return STDMAX(size_t(1), length-m_inputPosition);\
 	}
@@ -76,12 +66,4 @@
 #define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable)	\
 	FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable)
 
-#if CRYPTOPP_MSC_VERSION
-# pragma warning(pop)
-#endif
-
-#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
-# pragma GCC diagnostic pop
-#endif
-
 #endif

+ 9 - 1
include/cryptlib/gcm.h

@@ -10,6 +10,12 @@
 #include "authenc.h"
 #include "modes.h"
 
+// Clang 3.3 integrated assembler crash on Linux. Clang 3.4 due to compiler
+// error with .intel_syntax, http://llvm.org/bugs/show_bug.cgi?id=24232
+#if CRYPTOPP_BOOL_X32 || defined(CRYPTOPP_DISABLE_MIXED_ASM)
+# define CRYPTOPP_DISABLE_GCM_ASM 1
+#endif
+
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \enum GCM_TablesOption
@@ -29,6 +35,8 @@ public:
 	// AuthenticatedSymmetricCipher
 	std::string AlgorithmName() const
 		{return GetBlockCipher().AlgorithmName() + std::string("/GCM");}
+	std::string AlgorithmProvider() const
+		{return GetBlockCipher().AlgorithmProvider();}
 	size_t MinKeyLength() const
 		{return GetBlockCipher().MinKeyLength();}
 	size_t MaxKeyLength() const
@@ -72,7 +80,7 @@ protected:
 	virtual BlockCipher & AccessBlockCipher() =0;
 	virtual GCM_TablesOption GetTablesOption() const =0;
 
-	const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();};
+	const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();}
 	byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
 	byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;}
 	byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;}

+ 27 - 10
include/cryptlib/gf2n.h

@@ -28,7 +28,7 @@ class CRYPTOPP_DLL PolynomialMod2
 public:
 	/// \name ENUMS, EXCEPTIONS, and TYPEDEFS
 	//@{
-		/// \brief Excpetion thrown when divide by zero is encountered
+		/// \brief Exception thrown when divide by zero is encountered
 		class DivideByZero : public Exception
 		{
 		public:
@@ -65,23 +65,23 @@ public:
 			{Randomize(rng, bitcount);}
 
 		/// \brief Provides x^i
-		/// \returns x^i
+		/// \return x^i
 		static PolynomialMod2 CRYPTOPP_API Monomial(size_t i);
 		/// \brief Provides x^t0 + x^t1 + x^t2
-		/// \returns x^t0 + x^t1 + x^t2
+		/// \return x^t0 + x^t1 + x^t2
 		static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2);
 		/// \brief Provides x^t0 + x^t1 + x^t2 + x^t3 + x^t4
-		/// \returns x^t0 + x^t1 + x^t2 + x^t3 + x^t4
+		/// \return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
 		static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4);
 		/// \brief Provides x^(n-1) + ... + x + 1
-		/// \returns x^(n-1) + ... + x + 1
+		/// \return x^(n-1) + ... + x + 1
 		static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n);
 
 		/// \brief The Zero polinomial
-		/// \returns the zero polynomial
+		/// \return the zero polynomial
 		static const PolynomialMod2 & CRYPTOPP_API Zero();
 		/// \brief The One polinomial
-		/// \returns the one polynomial
+		/// \return the one polynomial
 		static const PolynomialMod2 & CRYPTOPP_API One();
 	//@}
 
@@ -246,6 +246,7 @@ public:
 
 private:
 	friend class GF2NT;
+	friend class GF2NT233;
 
 	SecWordBlock reg;
 };
@@ -344,26 +345,42 @@ public:
 
 	const Element& MultiplicativeInverse(const Element &a) const;
 
-private:
+protected:
 	const Element& Reduced(const Element &a) const;
 
 	unsigned int t0, t1;
 	mutable PolynomialMod2 result;
 };
 
+/// \brief GF(2^n) for b233 and k233
+/// \details GF2NT233 is a specialization of GF2NT that provides Multiply()
+///   and Square() operations when carryless multiplies is available.
+class CRYPTOPP_DLL GF2NT233 : public GF2NT
+{
+public:
+	// polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
+	GF2NT233(unsigned int t0, unsigned int t1, unsigned int t2);
+
+	GF2NP * Clone() const {return new GF2NT233(*this);}
+
+	const Element& Multiply(const Element &a, const Element &b) const;
+
+	const Element& Square(const Element &a) const;
+};
+
 /// \brief GF(2^n) with Pentanomial Basis
 class CRYPTOPP_DLL GF2NPP : public GF2NP
 {
 public:
 	// polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4
 	GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4)
-		: GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t0(t0), t1(t1), t2(t2), t3(t3) {}
+		: GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t1(t1), t2(t2), t3(t3) {}
 
 	GF2NP * Clone() const {return new GF2NPP(*this);}
 	void DEREncode(BufferedTransformation &bt) const;
 
 private:
-	unsigned int t0, t1, t2, t3;
+	unsigned int t1, t2, t3;
 };
 
 // construct new GF2NP from the ASN.1 sequence Characteristic-two

+ 232 - 57
include/cryptlib/gfpcrypt.h

@@ -47,8 +47,8 @@ public:
     /// \param rng a RandomNumberGenerator derived class
     /// \param pbits the size of p, in bits
     /// \details This function overload of Initialize() creates a new private key because it
-    ///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-    ///   then use one of the other Initialize() overloads.
+    ///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+    ///  then use one of the other Initialize() overloads.
     void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
         {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
 
@@ -69,10 +69,29 @@ public:
     void BERDecode(BufferedTransformation &bt);
     void DEREncode(BufferedTransformation &bt) const;
 
-    // GeneratibleCryptoMaterial interface
-    /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
+    /// \brief Generate a random key
+    /// \param rng a RandomNumberGenerator to produce keying material
+    /// \param alg additional initialization parameters
+    /// \details Recognised NameValuePairs are ModulusSize and
+    ///  SubgroupOrderSize (optional)
+    /// \throw KeyingErr if a key can't be generated or algorithm parameters
+    ///  are invalid
     void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+    /// \brief Get a named value
+    /// \param name the name of the object or value to retrieve
+    /// \param valueType reference to a variable that receives the value
+    /// \param pValue void pointer to a variable that receives the value
+    /// \return true if the value was retrieved, false otherwise
+    /// \details GetVoidValue() retrieves the value of name if it exists.
+    /// \note GetVoidValue() is an internal function and should be implemented
+    ///  by derived classes. Users should use one of the other functions instead.
+    /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(),
+    ///  GetRequiredParameter() and GetRequiredIntParameter()
     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+
+    /// \brief Initialize or reinitialize this key
+    /// \param source NameValuePairs to assign
     void AssignFrom(const NameValuePairs &source);
 
     // DL_GroupParameters
@@ -80,26 +99,70 @@ public:
     Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
     bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
     bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
+
+    /// \brief Determine if subgroup membership check is fast
+    /// \return true or false
     bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
 
-    // Cygwin i386 crash at -O3; see http://github.com/weidai11/cryptopp/issues/40.
+    /// \brief Encodes the element
+    /// \param reversible flag indicating the encoding format
+    /// \param element reference to the element to encode
+    /// \param encoded destination byte array for the encoded element
+    /// \details EncodeElement() must be implemented in a derived class.
+    /// \pre <tt>COUNTOF(encoded) == GetEncodedElementSize()</tt>
+    /// \sa GetEncodedElementSize(), DecodeElement(), <A
+    ///  HREF="http://github.com/weidai11/cryptopp/issues/40">Cygwin
+    ///  i386 crash at -O3</A>
     void EncodeElement(bool reversible, const Element &element, byte *encoded) const;
+
+    /// \brief Retrieve the encoded element's size
+    /// \param reversible flag indicating the encoding format
+    /// \return encoded element's size, in bytes
+    /// \details The format of the encoded element varies by the underlying
+    ///  type of the element and the reversible flag.
+    /// \sa EncodeElement(), DecodeElement()
     unsigned int GetEncodedElementSize(bool reversible) const;
 
+    /// \brief Decodes the element
+    /// \param encoded byte array with the encoded element
+    /// \param checkForGroupMembership flag indicating if the element should be validated
+    /// \return Element after decoding
+    /// \details DecodeElement() must be implemented in a derived class.
+    /// \pre <tt>COUNTOF(encoded) == GetEncodedElementSize()</tt>
+    /// \sa GetEncodedElementSize(), EncodeElement()
     Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
+
+    /// \brief Converts an element to an Integer
+    /// \param element the element to convert to an Integer
+    /// \return Element after converting to an Integer
+    /// \details ConvertElementToInteger() must be implemented in a derived class.
     Integer ConvertElementToInteger(const Element &element) const
         {return element;}
+
+    /// \brief Retrieve the maximum exponent for the group
+    /// \return the maximum exponent for the group
     Integer GetMaxExponent() const;
-    static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
 
+    /// \brief Retrieve the OID of the algorithm
+    /// \return OID of the algorithm
     OID GetAlgorithmID() const;
 
+    /// \brief Retrieve the modulus for the group
+    /// \return the modulus for the group
     virtual const Integer & GetModulus() const =0;
+
+    /// \brief Set group parameters
+    /// \param p the prime modulus
+    /// \param g the group generator
     virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
 
+    /// \brief Set subgroup order
+    /// \param q the subgroup order
     void SetSubgroupOrder(const Integer &q)
         {m_q = q; ParametersChanged();}
 
+    static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
+
 protected:
     Integer ComputeGroupOrder(const Integer &modulus) const
         {return modulus-(GetFieldType() == 1 ? 1 : -1);}
@@ -137,7 +200,12 @@ public:
     DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
 
     // IntegerGroupParameters
+    /// \brief Retrieve the modulus for the group
+    /// \return the modulus for the group
     const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
+
+    /// \brief Retrieves a reference to the group generator
+    /// \return const reference to the group generator
     const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
 
     void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g)        // these have to be set together
@@ -158,11 +226,37 @@ class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBas
 public:
     virtual ~DL_GroupParameters_GFP() {}
 
-    // DL_GroupParameters
+    /// \brief Determines if an element is an identity
+    /// \param element element to check
+    /// \return true if the element is an identity, false otherwise
+    /// \details The identity element or or neutral element is a special element
+    ///  in a group that leaves other elements unchanged when combined with it.
+    /// \details IsIdentity() must be implemented in a derived class.
     bool IsIdentity(const Integer &element) const {return element == Integer::One();}
+
+    /// \brief Exponentiates a base to multiple exponents
+    /// \param results an array of Elements
+    /// \param base the base to raise to the exponents
+    /// \param exponents an array of exponents
+    /// \param exponentsCount the number of exponents in the array
+    /// \details SimultaneousExponentiate() raises the base to each exponent in
+    ///  the exponents array and stores the result at the respective position in
+    ///  the results array.
+    /// \details SimultaneousExponentiate() must be implemented in a derived class.
+    /// \pre <tt>COUNTOF(results) == exponentsCount</tt>
+    /// \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
     void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
 
-    // NameValuePairs interface
+    /// \brief Get a named value
+    /// \param name the name of the object or value to retrieve
+    /// \param valueType reference to a variable that receives the value
+    /// \param pValue void pointer to a variable that receives the value
+    /// \return true if the value was retrieved, false otherwise
+    /// \details GetVoidValue() retrieves the value of name if it exists.
+    /// \note GetVoidValue() is an internal function and should be implemented
+    ///  by derived classes. Users should use one of the other functions instead.
+    /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(),
+    ///  GetRequiredParameter() and GetRequiredIntParameter()
     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
     {
         return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
@@ -188,8 +282,28 @@ protected:
     unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
 };
 
+/// ElGamal encryption for safe interop
+/// \sa <A HREF="https://eprint.iacr.org/2021/923.pdf">On the
+///  (in)security of ElGamal in OpenPGP</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/1059">Issue 1059</A>,
+///  <A HREF="https://nvd.nist.gov/vuln/detail/CVE-2021-40530">CVE-2021-40530</A>
+/// \since Crypto++ 8.6
+class CRYPTOPP_DLL DL_GroupParameters_ElGamal : public DL_GroupParameters_GFP_DefaultSafePrime
+{
+public:
+    typedef NoCofactorMultiplication DefaultCofactorOption;
+
+    virtual ~DL_GroupParameters_ElGamal() {}
+
+	Integer GetMaxExponent() const
+	{
+		return GetSubgroupOrder()-1;
+	}
+};
+
 /// \brief GDSA algorithm
 /// \tparam T FieldElement type or class
+/// \details FieldElement <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
 {
@@ -224,8 +338,9 @@ public:
 /// \brief DSA signature algorithm based on RFC 6979
 /// \tparam T FieldElement type or class
 /// \tparam H HashTransformation derived class
+/// \details FieldElement <tt>T</tt> can be Integer, ECP or EC2N.
 /// \sa <a href="http://tools.ietf.org/rfc/rfc6979.txt">RFC 6979, Deterministic Usage of the
-///   Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)</a>
+///  Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)</a>
 /// \since Crypto++ 6.0
 template <class T, class H>
 class DL_Algorithm_DSA_RFC6979 : public DL_Algorithm_GDSA<T>, public DeterministicSignatureAlgorithm
@@ -357,7 +472,7 @@ protected:
         else // block.size() < rlen
         {
             size_t offset = rlen - block.size();
-            memset(t, '\x00', offset);
+            std::memset(t, '\x00', offset);
             std::memcpy(t + offset, block, rlen - offset);
         }
 
@@ -380,11 +495,12 @@ private:
 
 /// \brief German Digital Signature Algorithm
 /// \tparam T FieldElement type or class
+/// \details FieldElement <tt>T</tt> can be Integer, ECP or EC2N.
 /// \details The Digital Signature Scheme ECGDSA does not define the algorithm over integers. Rather, the
-///   signature algorithm is only defined over elliptic curves. However, The library design is such that the
-///   generic algorithm reside in <tt>gfpcrypt.h</tt>.
+///  signature algorithm is only defined over elliptic curves. However, the library design is such that the
+///  generic algorithm reside in <tt>gfpcrypt.h</tt>.
 /// \sa Erwin Hess, Marcus Schafheutle, and Pascale Serf <A HREF="http://www.teletrust.de/fileadmin/files/oid/ecgdsa_final.pdf">
-///   The Digital Signature Scheme ECGDSA (October 24, 2006)</A>
+///  The Digital Signature Scheme ECGDSA (October 24, 2006)</A>
 template <class T>
 class DL_Algorithm_GDSA_ISO15946 : public DL_ElgamalLikeSignatureAlgorithm<T>
 {
@@ -426,6 +542,7 @@ CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_DSA_RFC6979<Integer, SHA512>;
 
 /// \brief NR algorithm
 /// \tparam T FieldElement type or class
+/// \details FieldElement <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
 {
@@ -502,8 +619,8 @@ public:
     /// \param rng a RandomNumberGenerator derived class
     /// \param modulusBits the size of the modulus, in bits
     /// \details This function overload of Initialize() creates a new private key because it
-    ///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-    ///   then use one of the other Initialize() overloads.
+    ///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+    ///  then use one of the other Initialize() overloads.
     void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
         {this->GenerateRandomWithKeySize(rng, modulusBits);}
 
@@ -512,8 +629,8 @@ public:
     /// \param p the modulus
     /// \param g the generator
     /// \details This function overload of Initialize() creates a new private key because it
-    ///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-    ///   then use one of the other Initialize() overloads.
+    ///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+    ///  then use one of the other Initialize() overloads.
     void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
         {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
 
@@ -523,8 +640,8 @@ public:
     /// \param q the subgroup order
     /// \param g the generator
     /// \details This function overload of Initialize() creates a new private key because it
-    ///   takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
-    ///   then use one of the other Initialize() overloads.
+    ///  takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
+    ///  then use one of the other Initialize() overloads.
     void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
         {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
 
@@ -570,6 +687,19 @@ struct DL_CryptoKeys_GFP
     typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
 };
 
+/// ElGamal encryption keys for safe interop
+/// \sa <A HREF="https://eprint.iacr.org/2021/923.pdf">On the
+///  (in)security of ElGamal in OpenPGP</A>,
+///  <A HREF="https://github.com/weidai11/cryptopp/issues/1059">Issue 1059</A>,
+///  <A HREF="https://nvd.nist.gov/vuln/detail/CVE-2021-40530">CVE-2021-40530</A>
+/// \since Crypto++ 8.6
+struct DL_CryptoKeys_ElGamal
+{
+    typedef DL_GroupParameters_ElGamal GroupParameters;
+    typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
+    typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
+};
+
 /// \brief DSA signature scheme
 /// \tparam H HashTransformation derived class
 /// \sa <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
@@ -598,21 +728,61 @@ struct NR : public DL_SS<
 /// \brief DSA group parameters
 /// \details These are GF(p) group parameters that are allowed by the DSA standard
 /// \sa DL_Keys_DSA
+/// \since Crypto++ 1.0
 class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
 {
 public:
     virtual ~DL_GroupParameters_DSA() {}
 
-    /*! also checks that the lengths of p and q are allowed by the DSA standard */
+    /// \brief Check the group for errors
+    /// \param rng RandomNumberGenerator for objects which use randomized testing
+    /// \param level level of thoroughness
+    /// \return true if the tests succeed, false otherwise
+    /// \details ValidateGroup() also checks that the lengths of p and q are allowed
+    ///  by the DSA standard.
+    /// \details There are four levels of thoroughness:
+    ///  <ul>
+    ///  <li>0 - using this object won't cause a crash or exception
+    ///  <li>1 - this object will probably function, and encrypt, sign, other operations correctly
+    ///  <li>2 - ensure this object will function correctly, and perform reasonable security checks
+    ///  <li>3 - perform reasonable security checks, and do checks that may take a long time
+    ///  </ul>
+    /// \details Level 0 does not require a RandomNumberGenerator. A NullRNG() can be used for level 0.
+    ///  Level 1 may not check for weak keys and such. Levels 2 and 3 are recommended.
     bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
-    /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
-    /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
+
+    /// \brief Generate a random key or crypto parameters
+    /// \param rng a RandomNumberGenerator to produce keying material
+    /// \param alg additional initialization parameters
+    /// \details NameValuePairs can be ModulusSize alone; or Modulus, SubgroupOrder, and
+    ///  SubgroupGenerator. ModulusSize must be between <tt>DSA::MIN_PRIME_LENGTH</tt> and
+    ///  <tt>DSA::MAX_PRIME_LENGTH</tt>, and divisible by <tt>DSA::PRIME_LENGTH_MULTIPLE</tt>.
+    /// \details An example of changing the modulus size using NameValuePairs is shown below.
+    /// <pre>
+    ///  AlgorithmParameters params = MakeParameters
+    ///    (Name::ModulusSize(), 2048);
+    ///
+    ///  DL_GroupParameters_DSA groupParams;
+    ///  groupParams.GenerateRandom(prng, params);
+    /// </pre>
+    /// \throw KeyingErr if a key can't be generated or algorithm parameters are invalid.
     void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
 
+    /// \brief Check the prime length for errors
+    /// \param pbits number of bits in the prime number
+    /// \return true if the tests succeed, false otherwise
     static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
         {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
 
-    enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
+    /// \brief DSA prime length
+    enum {
+        /// \brief Minimum prime length
+        MIN_PRIME_LENGTH = 1024,
+        /// \brief Maximum prime length
+        MAX_PRIME_LENGTH = 3072,
+        /// \brief Prime length multiple
+        PRIME_LENGTH_MULTIPLE = 1024
+    };
 };
 
 template <class H>
@@ -620,6 +790,7 @@ class DSA2;
 
 /// \brief DSA keys
 /// \sa DL_GroupParameters_DSA
+/// \since Crypto++ 1.0
 struct DL_Keys_DSA
 {
     typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
@@ -629,25 +800,25 @@ struct DL_Keys_DSA
 /// \brief DSA signature scheme
 /// \tparam H HashTransformation derived class
 /// \details The class is named DSA2 instead of DSA for backwards compatibility because
-///   DSA was a non-template class.
+///  DSA was a non-template class.
 /// \details DSA default method GenerateRandom uses a 2048-bit modulus and a 224-bit subgoup by default.
-///   The modulus can be changed using the following code:
+///  The modulus can be changed using the following code:
 /// <pre>
-///   DSA::PrivateKey privateKey;
-///   privateKey.GenerateRandomWithKeySize(prng, 2048);
+///  DSA::PrivateKey privateKey;
+///  privateKey.GenerateRandomWithKeySize(prng, 2048);
 /// </pre>
 /// \details The subgroup order can be changed using the following code:
 /// <pre>
-///   AlgorithmParameters params = MakeParameters
-///     (Name::ModulusSize(), 2048)
-///     (Name::SubgroupOrderSize(), 256);
+///  AlgorithmParameters params = MakeParameters
+///    (Name::ModulusSize(), 2048)
+///    (Name::SubgroupOrderSize(), 256);
 ///
-///   DSA::PrivateKey privateKey;
-///   privateKey.GenerateRandom(prng, params);
+///  DSA::PrivateKey privateKey;
+///  privateKey.GenerateRandom(prng, params);
 /// </pre>
 /// \sa <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3,
-///   <a href="https://www.cryptopp.com/wiki/Digital_Signature_Algorithm">Digital Signature Algorithm</a> on the wiki, and
-///   <a href="https://www.cryptopp.com/wiki/NameValuePairs">NameValuePairs</a> on the wiki.
+///  <a href="https://www.cryptopp.com/wiki/Digital_Signature_Algorithm">Digital Signature Algorithm</a> on the wiki, and
+///  <a href="https://www.cryptopp.com/wiki/NameValuePairs">NameValuePairs</a> on the wiki.
 /// \since Crypto++ 1.0 for DSA, Crypto++ 5.6.2 for DSA2, Crypto++ 6.1 for 2048-bit modulus.
 template <class H>
 class DSA2 : public DL_SS<
@@ -688,12 +859,12 @@ CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<D
 /// \tparam DHAES_MODE flag indicating DHAES mode
 /// \tparam LABEL_OCTETS flag indicating the label is octet count
 /// \details DL_EncryptionAlgorithm_Xor is based on an early P1363 draft, which itself appears to be based on an
-///   early Certicom SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used it in its Integrated
-///   Ecryption Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
+///  early Certicom SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used it in its Integrated
+///  Ecryption Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
 /// \details If you need this method for Crypto++ 4.2 compatibility, then use the ECIES template class with
-///   <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
+///  <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
 /// \details If you need this method for Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES template class with
-///   <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=ture</tt> and <tt>LABEL_OCTETS=false</tt>.
+///  <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
 /// \details Bouncy Castle 1.54 and Botan 1.11 compatibility are the default template parameters.
 /// \since Crypto++ 4.0
 template <class MAC, bool DHAES_MODE, bool LABEL_OCTETS=false>
@@ -704,7 +875,7 @@ public:
 
     bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
     size_t GetSymmetricKeyLength(size_t plaintextLength) const
-        {return plaintextLength + static_cast<size_t>(MAC::DIGESTSIZE);}
+        {return plaintextLength + static_cast<size_t>(MAC::DEFAULT_KEYLENGTH);}
     size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
         {return plaintextLength + static_cast<size_t>(MAC::DIGESTSIZE);}
     size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
@@ -778,7 +949,11 @@ public:
     }
 };
 
-/// _
+/// \brief P1363 based Key Derivation Method
+/// \tparam T FieldElement type or class
+/// \tparam DHAES_MODE flag indicating DHAES mode
+/// \tparam KDF key derivation function
+/// \details FieldElement <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T, bool DHAES_MODE, class KDF>
 class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
 {
@@ -813,32 +988,32 @@ public:
 /// \tparam DHAES_MODE flag indicating if the MAC includes addition context parameters such as the label
 /// \tparam LABEL_OCTETS flag indicating if the label size is specified in octets or bits
 /// \details DLIES is an Integer based Integrated Encryption Scheme (IES). The scheme combines a Key Encapsulation Method (KEM)
-///   with a Data Encapsulation Method (DEM) and a MAC tag. The scheme is
-///   <A HREF="http://en.wikipedia.org/wiki/ciphertext_indistinguishability">IND-CCA2</A>, which is a strong notion of security.
-///   You should prefer an Integrated Encryption Scheme over homegrown schemes.
+///  with a Data Encapsulation Method (DEM) and a MAC tag. The scheme is
+///  <A HREF="http://en.wikipedia.org/wiki/ciphertext_indistinguishability">IND-CCA2</A>, which is a strong notion of security.
+///  You should prefer an Integrated Encryption Scheme over homegrown schemes.
 /// \details The library's original implementation is based on an early P1363 draft, which itself appears to be based on an early Certicom
-///   SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used the early draft in its Integrated Ecryption
-///   Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
+///  SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used the early draft in its Integrated Ecryption
+///  Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
 /// \details If you desire an Integrated Encryption Scheme with Crypto++ 4.2 compatibility, then use the DLIES template class with
-///   <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
+///  <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
 /// \details If you desire an Integrated Encryption Scheme with Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the DLIES
-///   template class with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
+///  template class with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
 /// \details The default template parameters ensure compatibility with Bouncy Castle 1.54 and Botan 1.11. The combination of
-///   <tt>IncompatibleCofactorMultiplication</tt> and <tt>DHAES_MODE=true</tt> is recommended for best efficiency and security.
-///   SHA1 is used for compatibility reasons, but it can be changed if desired. SHA-256 or another hash will likely improve the
-///   security provided by the MAC. The hash is also used in the key derivation function as a PRF.
+///  <tt>IncompatibleCofactorMultiplication</tt> and <tt>DHAES_MODE=true</tt> is recommended for best efficiency and security.
+///  SHA1 is used for compatibility reasons, but it can be changed if desired. SHA-256 or another hash will likely improve the
+///  security provided by the MAC. The hash is also used in the key derivation function as a PRF.
 /// \details Below is an example of constructing a Crypto++ 4.2 compatible DLIES encryptor and decryptor.
 /// <pre>
-///     AutoSeededRandomPool prng;
-///     DL_PrivateKey_GFP<DL_GroupParameters_GFP> key;
-///     key.Initialize(prng, 2048);
+///    AutoSeededRandomPool prng;
+///    DL_PrivateKey_GFP<DL_GroupParameters_GFP> key;
+///    key.Initialize(prng, 2048);
 ///
-///     DLIES<SHA1,NoCofactorMultiplication,true,true>::Decryptor decryptor(key);
-///     DLIES<SHA1,NoCofactorMultiplication,true,true>::Encryptor encryptor(decryptor);
+///    DLIES<SHA1,NoCofactorMultiplication,true,true>::Decryptor decryptor(key);
+///    DLIES<SHA1,NoCofactorMultiplication,true,true>::Encryptor encryptor(decryptor);
 /// </pre>
 /// \sa ECIES, <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">Discrete Log Integrated Encryption Scheme (DLIES)</a>,
-///   Martínez, Encinas, and Ávila's <A HREF="http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf">A Survey of the Elliptic
-///   Curve Integrated Encryption Schemes</A>
+///  Martínez, Encinas, and Ávila's <A HREF="http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf">A Survey of the Elliptic
+///  Curve Integrated Encryption Schemes</A>
 /// \since Crypto++ 4.0, Crypto++ 5.7 for Bouncy Castle and Botan compatibility
 template <class HASH = SHA1, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true, bool LABEL_OCTETS=false>
 struct DLIES

+ 3 - 0
include/cryptlib/hashfwd.h

@@ -20,6 +20,9 @@ class SHA3_256;
 class SHA3_384;
 class SHA3_512;
 
+class SHAKE128;
+class SHAKE256;
+
 class Tiger;
 class RIPEMD128;
 class RIPEMD160;

+ 67 - 0
include/cryptlib/hc128.h

@@ -0,0 +1,67 @@
+// hc128.h - written and placed in the public domain by Jeffrey Walton
+//           based on public domain code by Hongjun Wu.
+//
+//           The reference materials and source files are available at
+//           The eSTREAM Project, http://www.ecrypt.eu.org/stream/e2-hc128.html.
+
+/// \file hc128.h
+/// \brief Classes for HC-128 stream cipher
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/e2-hc128.html">The
+///   eSTREAM Project | HC-128</A> and
+///   <A HREF="https://www.cryptopp.com/wiki/HC-128">Crypto++ Wiki | HC-128</A>.
+/// \since Crypto++ 8.0
+
+#ifndef CRYPTOPP_HC128_H
+#define CRYPTOPP_HC128_H
+
+#include "strciphr.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief HC-128 stream cipher information
+/// \since Crypto++ 8.0
+struct HC128Info : public FixedKeyLength<16, SimpleKeyingInterface::UNIQUE_IV, 16>
+{
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "HC-128"; }
+};
+
+/// \brief HC-128 stream cipher implementation
+/// \since Crypto++ 8.0
+class HC128Policy : public AdditiveCipherConcretePolicy<word32, 16>, public HC128Info
+{
+protected:
+	void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+	void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+	void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
+	bool CanOperateKeystream() const { return true; }
+	bool CipherIsRandomAccess() const { return false; }
+
+	void GenerateKeystream(word32* keystream);
+	void SetupUpdate();
+
+private:
+	FixedSizeSecBlock<word32, 16> m_X;
+	FixedSizeSecBlock<word32, 16> m_Y;
+	FixedSizeSecBlock<word32, 8> m_key;
+	FixedSizeSecBlock<word32, 8> m_iv;
+	word32 m_T[1024];
+	word32 m_ctr;
+};
+
+/// \brief HC-128 stream cipher
+/// \details HC-128 is a stream cipher developed by Hongjun Wu. HC-128 is one of the
+///   final four Profile 1 (software) ciphers selected for the eSTREAM portfolio.
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/e2-hc128.html">The
+///   eSTREAM Project | HC-128</A> and
+///   <A HREF="https://www.cryptopp.com/wiki/HC-128">Crypto++ Wiki | HC-128</A>.
+/// \since Crypto++ 8.0
+struct HC128 : public HC128Info, public SymmetricCipherDocumentation
+{
+	typedef SymmetricCipherFinal<ConcretePolicyHolder<HC128Policy, AdditiveCipherTemplate<> >, HC128Info> Encryption;
+	typedef Encryption Decryption;
+};
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_HC128_H

+ 69 - 0
include/cryptlib/hc256.h

@@ -0,0 +1,69 @@
+// hc256.h - written and placed in the public domain by Jeffrey Walton
+//           based on public domain code by Hongjun Wu.
+//
+//           The reference materials and source files are available at
+//           The eSTREAM Project, http://www.ecrypt.eu.org/stream/hc256.html.
+
+/// \file hc256.h
+/// \brief Classes for HC-256 stream cipher
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/hc256.html">The
+///   eSTREAM Project | HC-256</A> and
+///   <A HREF="https://www.cryptopp.com/wiki/HC-128">Crypto++ Wiki | HC-128</A>.
+/// \since Crypto++ 8.0
+
+#ifndef CRYPTOPP_HC256_H
+#define CRYPTOPP_HC256_H
+
+#include "strciphr.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief HC-256 stream cipher information
+/// \since Crypto++ 8.0
+struct HC256Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 32>
+{
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "HC-256"; }
+};
+
+/// \brief HC-256 stream cipher implementation
+/// \since Crypto++ 8.0
+class HC256Policy : public AdditiveCipherConcretePolicy<word32, 4>, public HC256Info
+{
+protected:
+	void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+	void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+	void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
+	bool CanOperateKeystream() const { return true; }
+	bool CipherIsRandomAccess() const { return false; }
+
+	word32 H1(word32 u);
+	word32 H2(word32 u);
+
+	void GenerateKeystream(word32* keystream);
+	word32 Generate();
+
+private:
+	FixedSizeSecBlock<word32, 8> m_key;
+	FixedSizeSecBlock<word32, 8> m_iv;
+	word32 m_P[1024];
+	word32 m_Q[1024];
+	word32 m_ctr;
+};
+
+/// \brief HC-256 stream cipher
+/// \details HC-256 is a stream cipher developed by Hongjun Wu. HC-256 is the
+///   successor to HC-128 from the eSTREAM project.
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/hc256.html">The
+///   eSTREAM Project | HC-256</A> and
+///   <A HREF="https://www.cryptopp.com/wiki/HC-128">Crypto++ Wiki | HC-128</A>.
+/// \since Crypto++ 8.0
+struct HC256 : public HC256Info, public SymmetricCipherDocumentation
+{
+	typedef SymmetricCipherFinal<ConcretePolicyHolder<HC256Policy, AdditiveCipherTemplate<> >, HC256Info> Encryption;
+	typedef Encryption Decryption;
+};
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_HC256_H

+ 81 - 0
include/cryptlib/hight.h

@@ -0,0 +1,81 @@
+// hight.h - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton
+//           Based on "HIGHT: A New Block Cipher Suitable for Low-Resource Device"
+//           by Deukjo Hong, Jaechul Sung, Seokhie Hong, Jongin Lim, Sangjin Lee,
+//           Bon-Seok Koo, Changhoon Lee, Donghoon Chang, Jesang Lee, Kitae Jeong,
+//           Hyun Kim, Jongsung Kim, and Seongtaek Chee
+
+/// \file hight.h
+/// \brief Classes for the HIGHT block cipher
+/// \since Crypto++ 8.0
+
+#ifndef CRYPTOPP_HIGHT_H
+#define CRYPTOPP_HIGHT_H
+
+#include "config.h"
+#include "seckey.h"
+#include "secblock.h"
+#include "algparam.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief HIGHT block cipher information
+/// \since Crypto++ 8.0
+struct HIGHT_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
+{
+    static const std::string StaticAlgorithmName()
+    {
+        // Format is Cipher-Blocksize
+        return "HIGHT";
+    }
+};
+
+/// \brief HIGHT 64-bit block cipher
+/// \details HIGHT provides 64-bit block size. The valid key size is 128-bits.
+/// \note Crypto++ provides a byte oriented implementation
+/// \sa <a href="http://www.cryptopp.com/wiki/HIGHT">HIGHT</a>,
+///   <a href="https://seed.kisa.or.kr/">Korea Internet &amp; Security
+///   Agency</a> website
+/// \since Crypto++ 8.0
+class CRYPTOPP_NO_VTABLE HIGHT : public HIGHT_Info, public BlockCipherDocumentation
+{
+public:
+    /// \brief HIGHT block cipher transformation functions
+    /// \details Provides implementation common to encryption and decryption
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<HIGHT_Info>
+    {
+    protected:
+        void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
+
+        FixedSizeSecBlock<byte, 136> m_rkey;
+        mutable FixedSizeSecBlock<word32, 8> m_xx;
+    };
+
+    /// \brief Encryption transformation
+    /// \details Enc provides implementation for encryption transformation.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Enc : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+    };
+
+    /// \brief Decryption transformation
+    /// \details Dec provides implementation for decryption transformation.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Dec : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+    };
+
+    typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+    typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+typedef HIGHT::Encryption HIGHTEncryption;
+typedef HIGHT::Decryption HIGHTDecryption;
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_HIGHT_H

+ 9 - 8
include/cryptlib/hkdf.h

@@ -9,6 +9,7 @@
 
 #include "cryptlib.h"
 #include "secblock.h"
+#include "algparam.h"
 #include "hmac.h"
 
 NAMESPACE_BEGIN(CryptoPP)
@@ -38,7 +39,7 @@ public:
 	}
 
 	// KeyDerivationFunction interface
-	size_t MaxDerivedLength() const {
+	size_t MaxDerivedKeyLength() const {
 		return static_cast<size_t>(T::DIGESTSIZE) * 255;
 	}
 
@@ -58,8 +59,8 @@ public:
 	/// \param saltLen the size of the salt buffer, in bytes
 	/// \param info the additional input buffer
 	/// \param infoLen the size of the info buffer, in bytes
-	/// \returns the number of iterations performed
-	/// \throws InvalidDerivedLength if <tt>derivedLen</tt> is invalid for the scheme
+	/// \return the number of iterations performed
+	/// \throw InvalidDerivedKeyLength if <tt>derivedLen</tt> is invalid for the scheme
 	/// \details DeriveKey() provides a standard interface to derive a key from
 	///   a seed and other parameters. Each class that derives from KeyDerivationFunction
 	///   provides an overload that accepts most parameters used by the derivation function.
@@ -91,8 +92,8 @@ protected:
 template <class T>
 size_t HKDF<T>::GetValidDerivedLength(size_t keylength) const
 {
-	if (keylength > MaxDerivedLength())
-		return MaxDerivedLength();
+	if (keylength > MaxDerivedKeyLength())
+		return MaxDerivedKeyLength();
 	return keylength;
 }
 
@@ -102,7 +103,7 @@ size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen,
 {
 	CRYPTOPP_ASSERT(secret && secretLen);
 	CRYPTOPP_ASSERT(derived && derivedLen);
-	CRYPTOPP_ASSERT(derivedLen <= MaxDerivedLength());
+	CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
 
 	ConstByteArrayParameter p;
 	SecByteBlock salt, info;
@@ -126,9 +127,9 @@ size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen, const byte *secret,
 {
 	CRYPTOPP_ASSERT(secret && secretLen);
 	CRYPTOPP_ASSERT(derived && derivedLen);
-	CRYPTOPP_ASSERT(derivedLen <= MaxDerivedLength());
+	CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
 
-	ThrowIfInvalidDerivedLength(derivedLen);
+	ThrowIfInvalidDerivedKeyLength(derivedLen);
 
 	// HKDF business logic. NULL is different than empty.
 	if (salt == NULLPTR)

+ 7 - 2
include/cryptlib/hmac.h

@@ -17,6 +17,8 @@ NAMESPACE_BEGIN(CryptoPP)
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HMAC_Base : public VariableKeyLength<16, 0, INT_MAX>, public MessageAuthenticationCode
 {
 public:
+	virtual ~HMAC_Base() {}
+
 	/// \brief Construct a HMAC_Base
 	HMAC_Base() : m_innerHashKeyed(false) {}
 	void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params);
@@ -50,8 +52,10 @@ template <class T>
 class HMAC : public MessageAuthenticationCodeImpl<HMAC_Base, HMAC<T> >
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE)
-	CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
+	CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE);
+	CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE);
+
+	virtual ~HMAC() {}
 
 	/// \brief Construct a HMAC
 	HMAC() {}
@@ -63,6 +67,7 @@ public:
 
 	static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";}
 	std::string AlgorithmName() const {return std::string("HMAC(") + m_hash.AlgorithmName() + ")";}
+	std::string AlgorithmProvider() const {return m_hash.AlgorithmProvider();}
 
 private:
 	HashTransformation & AccessHash() {return m_hash;}

+ 185 - 78
include/cryptlib/hmqv.h

@@ -1,5 +1,5 @@
 // hmqv.h - written and placed in the public domain by Uri Blumenthal
-//          Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files
+//          Shamelessly based upon Wei Dai's MQV source files
 
 #ifndef CRYPTOPP_HMQV_H
 #define CRYPTOPP_HMQV_H
@@ -29,59 +29,148 @@ public:
 
   virtual ~HMQV_Domain() {}
 
-  HMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
-
+  /// \brief Construct a HMQV domain
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
+  HMQV_Domain(bool clientRole = true)
+    : m_role(clientRole ? RoleClient : RoleServer) {}
+
+  /// \brief Construct a HMQV domain
+  /// \param params group parameters and options
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   HMQV_Domain(const GroupParameters &params, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
 
+  /// \brief Construct a HMQV domain
+  /// \param bt BufferedTransformation with group parameters and options
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   HMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.BERDecode(bt);}
-
+    {m_groupParameters.BERDecode(bt);}
+
+  /// \brief Construct a HMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1 is passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1>
   HMQV_Domain(T1 v1, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1);}
-
+    {m_groupParameters.Initialize(v1);}
+
+  /// \brief Construct a HMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \tparam T2 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param v2 second parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1, class T2>
   HMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1, v2);}
-
+    {m_groupParameters.Initialize(v1, v2);}
+
+  /// \brief Construct a HMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \tparam T2 template parameter used as a constructor parameter
+  /// \tparam T3 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param v2 second parameter
+  /// \param v3 third parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1, class T2, class T3>
   HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1, v2, v3);}
-
+    {m_groupParameters.Initialize(v1, v2, v3);}
+
+  /// \brief Construct a HMQV domain
+  /// \tparam T1 template parameter used as a constructor parameter
+  /// \tparam T2 template parameter used as a constructor parameter
+  /// \tparam T3 template parameter used as a constructor parameter
+  /// \tparam T4 template parameter used as a constructor parameter
+  /// \param v1 first parameter
+  /// \param v2 second parameter
+  /// \param v3 third parameter
+  /// \param v4 third parameter
+  /// \param clientRole flag indicating initiator or recipient
+  /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
+  /// \details <tt>clientRole = true</tt> indicates initiator, and
+  ///  <tt>clientRole = false</tt> indicates recipient or server.
   template <class T1, class T2, class T3, class T4>
   HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
     : m_role(clientRole ? RoleClient : RoleServer)
-  {m_groupParameters.Initialize(v1, v2, v3, v4);}
+    {m_groupParameters.Initialize(v1, v2, v3, v4);}
 
 public:
 
+  /// \brief Retrieves the group parameters for this domain
+  /// \return the group parameters for this domain as a const reference
   const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
-  GroupParameters & AccessGroupParameters(){return m_groupParameters;}
-
-  CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
 
-  /// return length of agreed value produced
-  unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
-  /// return length of static private keys in this domain
-  unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
-  /// return length of static public keys in this domain
-  unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
-
-  /// generate static private key
-  /*! \pre size of privateKey == PrivateStaticKeyLength() */
+  /// \brief Retrieves the group parameters for this domain
+  /// \return the group parameters for this domain as a non-const reference
+  GroupParameters & AccessGroupParameters() {return m_groupParameters;}
+
+  /// \brief Retrieves the crypto parameters for this domain
+  /// \return the crypto parameters for this domain as a non-const reference
+  CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
+
+  /// \brief Provides the size of the agreed value
+  /// \return size of agreed value produced in this domain
+  /// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
+  ///  which means the element is encoded in a non-reversible format. A
+  ///  non-reversible format means its a raw byte array, and it lacks presentation
+  ///  format like an ASN.1 BIT_STRING or OCTET_STRING.
+  unsigned int AgreedValueLength() const
+    {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
+
+  /// \brief Provides the size of the static private key
+  /// \return size of static private keys in this domain
+  /// \details The length is calculated using the byte count of the subgroup order.
+  unsigned int StaticPrivateKeyLength() const
+    {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
+
+  /// \brief Provides the size of the static public key
+  /// \return size of static public keys in this domain
+  /// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>,
+  ///  which means the element is encoded in a reversible format. A reversible
+  ///  format means it has a presentation format, and its an ANS.1 encoded element
+  ///  or point.
+  unsigned int StaticPublicKeyLength() const
+    {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
+
+  /// \brief Generate static private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer for the generated private key in this domain
+  /// \details The private key is a random scalar used as an exponent in the range
+  ///  <tt>[1,MaxExponent()]</tt>.
+  /// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
   void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
   {
     Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
     x.Encode(privateKey, StaticPrivateKeyLength());
   }
 
-  /// generate static public key
-  /*! \pre size of publicKey == PublicStaticKeyLength() */
+  /// \brief Generate a static public key from a private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer with the previously generated private key
+  /// \param publicKey a byte buffer for the generated public key in this domain
+  /// \details The public key is an element or point on the curve, and its stored
+  ///  in a revrsible format. A reversible format means it has a presentation
+  ///  format, and its an ANS.1 encoded element or point.
+  /// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
   void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
   {
     CRYPTOPP_UNUSED(rng);
@@ -91,10 +180,22 @@ public:
     params.EncodeElement(true, y, publicKey);
   }
 
+  /// \brief Provides the size of the ephemeral private key
+  /// \return size of ephemeral private keys in this domain
+  /// \details An ephemeral private key is a private key and public key.
+  ///  The serialized size is different than a static private key.
   unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
+
+  /// \brief Provides the size of the ephemeral public key
+  /// \return size of ephemeral public keys in this domain
+  /// \details An ephemeral public key is a public key.
+  ///  The serialized size is the same as a static public key.
   unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
 
-  /// return length of ephemeral private keys in this domain
+  /// \brief Generate ephemeral private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer for the generated private key in this domain
+  /// \pre <tt>COUNTOF(privateKey) == EphemeralPrivateKeyLength()</tt>
   void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
   {
     const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
@@ -104,28 +205,46 @@ public:
     params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
   }
 
-  /// return length of ephemeral public keys in this domain
+  /// \brief Generate ephemeral public key from a private key in this domain
+  /// \param rng a RandomNumberGenerator derived class
+  /// \param privateKey a byte buffer with the previously generated private key
+  /// \param publicKey a byte buffer for the generated public key in this domain
+  /// \pre <tt>COUNTOF(publicKey) == EphemeralPublicKeyLength()</tt>
   void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
   {
     CRYPTOPP_UNUSED(rng);
-    memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
+    std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
   }
 
-  /// derive agreed value from your private keys and couterparty's public keys, return false in case of failure
-  /*! \note The ephemeral public key will always be validated.
-  If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
-  \pre size of agreedValue == AgreedValueLength()
-  \pre length of staticPrivateKey == StaticPrivateKeyLength()
-  \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
-  \pre length of staticOtherPublicKey == StaticPublicKeyLength()
-  \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
-  */
+  /// \brief Derive agreed value or shared secret
+  /// \param agreedValue the shared secret
+  /// \param staticPrivateKey your long term private key
+  /// \param ephemeralPrivateKey your ephemeral private key
+  /// \param staticOtherPublicKey couterparty's long term public key
+  /// \param ephemeralOtherPublicKey couterparty's ephemeral public key
+  /// \param validateStaticOtherPublicKey flag indicating validation
+  /// \return true upon success, false in case of failure
+  /// \details Agree() performs the authenticated key agreement. Agree()
+  ///  derives a shared secret from your private keys and couterparty's
+  ///  public keys. Each instance or run of the protocol should use a new
+  ///  ephemeral key pair.
+  /// \details The other's ephemeral public key will always be validated at
+  ///  Level 1 to ensure it is a point on the curve.
+  ///  <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
+  ///  static public key is validated. If you have previously validated the
+  ///  couterparty's static public key, then use
+  ///  <tt>validateStaticOtherPublicKey=false</tt> to save time.
+  /// \pre <tt>COUNTOF(agreedValue) == AgreedValueLength()</tt>
+  /// \pre <tt>COUNTOF(staticPrivateKey) == StaticPrivateKeyLength()</tt>
+  /// \pre <tt>COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength()</tt>
+  /// \pre <tt>COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength()</tt>
+  /// \pre <tt>COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength()</tt>
   bool Agree(byte *agreedValue,
     const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
     const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
     bool validateStaticOtherPublicKey=true) const
   {
-    byte *XX = NULLPTR, *YY = NULLPTR, *AA = NULLPTR, *BB = NULLPTR;
+    const byte *XX = NULLPTR, *YY = NULLPTR, *AA = NULLPTR, *BB = NULLPTR;
     size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
 
     // Depending on the role, this will hold either A's or B's static
@@ -134,6 +253,7 @@ public:
 
     try
     {
+      this->GetMaterial().DoQuickSanityCheck();
       const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
 
       if(m_role == RoleServer)
@@ -142,63 +262,45 @@ public:
         Element B = params.ExponentiateBase(b);
         params.EncodeElement(true, B, tt);
 
-        XX = const_cast<byte*>(ephemeralOtherPublicKey);
+        XX = ephemeralOtherPublicKey;
         xxs = EphemeralPublicKeyLength();
-        YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
+        YY = ephemeralPrivateKey + StaticPrivateKeyLength();
         yys = EphemeralPublicKeyLength();
-        AA = const_cast<byte*>(staticOtherPublicKey);
+        AA = staticOtherPublicKey;
         aas = StaticPublicKeyLength();
         BB = tt.BytePtr();
         bbs = tt.SizeInBytes();
       }
-      else if(m_role == RoleClient)
+      else
       {
         Integer a(staticPrivateKey, StaticPrivateKeyLength());
         Element A = params.ExponentiateBase(a);
         params.EncodeElement(true, A, tt);
 
-        XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
+        XX = ephemeralPrivateKey + StaticPrivateKeyLength();
         xxs = EphemeralPublicKeyLength();
-        YY = const_cast<byte*>(ephemeralOtherPublicKey);
+        YY = ephemeralOtherPublicKey;
         yys = EphemeralPublicKeyLength();
         AA = tt.BytePtr();
         aas = tt.SizeInBytes();
-        BB = const_cast<byte*>(staticOtherPublicKey);
+        BB = staticOtherPublicKey;
         bbs = StaticPublicKeyLength();
       }
-      else
-      {
-        CRYPTOPP_ASSERT(0);
-        return false;
-      }
-
-      // DecodeElement calls ValidateElement at level 1. Level 1 only calls
-      // VerifyPoint to ensure the element is in G*. If the other's PublicKey is
-      // requested to be validated, we manually call ValidateElement at level 3.
-      Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
-      if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULLPTR))
-        return false;
 
-      // DecodeElement calls ValidateElement at level 1. Level 1 only calls
-      // VerifyPoint to ensure the element is in G*. Crank it up.
-      Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
-      if(!params.ValidateElement(3, VV2, NULLPTR))
-        return false;
+      Element VV1 = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
+      Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, true);
 
-      // const Integer& p = params.GetGroupOrder(); // not used, remove later
       const Integer& q = params.GetSubgroupOrder();
       const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
-
-      Integer d, e;
       SecByteBlock dd(len), ee(len);
 
       // Compute $d = \hat{H}(X, \hat{B})$
       Hash(NULLPTR, XX, xxs, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
-      d.Decode(dd.BytePtr(), dd.SizeInBytes());
+      Integer d(dd.BytePtr(), dd.SizeInBytes());
 
       // Compute $e = \hat{H}(Y, \hat{A})$
       Hash(NULLPTR, YY, yys, AA, aas, ee.BytePtr(), ee.SizeInBytes());
-      e.Decode(ee.BytePtr(), ee.SizeInBytes());
+      Integer e(ee.BytePtr(), ee.SizeInBytes());
 
       Element sigma;
       if(m_role == RoleServer)
@@ -225,16 +327,17 @@ public:
         Element B = params.DecodeElement(BB, false);
         Element Y = params.DecodeElement(YY, false);
 
-        Element t1 = params.ExponentiateElement(B, e);
-        Element t2 = m_groupParameters.MultiplyElements(Y, t1);
+        Element t3 = params.ExponentiateElement(B, e);
+        Element t4 = m_groupParameters.MultiplyElements(Y, t3);
 
         // $\sigma_A}=(Y \cdot B^{e})^{s_A}
-        sigma = params.ExponentiateElement(t2, s_A);
+        sigma = params.ExponentiateElement(t4, s_A);
       }
       Hash(&sigma, NULLPTR, 0, NULLPTR, 0, agreedValue, AgreedValueLength());
     }
     catch (DL_BadElement &)
     {
+      CRYPTOPP_ASSERT(0);
       return false;
     }
     return true;
@@ -258,9 +361,11 @@ protected:
       if (e1len != 0 || s1len != 0) {
         CRYPTOPP_ASSERT(0);
       }
-      Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
-      SecByteBlock sbb(x.MinEncodedSize());
-      x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
+      //Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
+      //SecByteBlock sbb(x.MinEncodedSize());
+      //x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
+      SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
+      GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
       hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
     } else {
       if (e1len == 0 || s1len == 0) {
@@ -289,10 +394,12 @@ protected:
 private:
 
   // The paper uses Initiator and Recipient - make it classical.
-  enum KeyAgreementRole{ RoleServer = 1, RoleClient };
+  enum KeyAgreementRole { RoleServer = 1, RoleClient };
 
-  DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
-  const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
+  DL_GroupParameters<Element> & AccessAbstractGroupParameters()
+    {return m_groupParameters;}
+  const DL_GroupParameters<Element> & GetAbstractGroupParameters() const
+    {return m_groupParameters;}
 
   GroupParameters m_groupParameters;
   KeyAgreementRole m_role;
@@ -301,7 +408,7 @@ private:
 /// \brief Hashed Menezes-Qu-Vanstone in GF(p)
 /// \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
 ///   Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
-/// \sa HMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
+/// \sa HMQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
 /// \since Crypto++ 5.6.4
 typedef HMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> HMQV;
 

+ 77 - 8
include/cryptlib/hrtimer.h

@@ -1,3 +1,8 @@
+// hrtimer.h - originally written and placed in the public domain by Wei Dai
+
+/// \file hrtimer.h
+/// \brief Classes for timers
+
 #ifndef CRYPTOPP_HRTIMER_H
 #define CRYPTOPP_HRTIMER_H
 
@@ -10,25 +15,77 @@
 NAMESPACE_BEGIN(CryptoPP)
 
 #ifdef HIGHRES_TIMER_AVAILABLE
+	/// \brief TimerWord is a 64-bit word
 	typedef word64 TimerWord;
 #else
+	/// \brief TimerWord is a clock_t
 	typedef clock_t TimerWord;
 #endif
 
 /// \brief Base class for timers
+/// \sa ThreadUserTimer, Timer
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase
 {
 public:
-	enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
+	/// \brief Unit of measure
+	/// \details Unit selects the unit of measure as returned by functions
+	///  ElapsedTimeAsDouble() and ElapsedTime().
+	/// \sa ElapsedTimeAsDouble, ElapsedTime
+	enum Unit {
+		/// \brief Timer unit is seconds
+		/// \details All timers support seconds
+		SECONDS = 0,
+		/// \brief Timer unit is milliseconds
+		/// \details All timers support milliseconds
+		MILLISECONDS,
+		/// \brief Timer unit is microseconds
+		/// \details The timer requires hardware support microseconds
+		MICROSECONDS,
+		/// \brief Timer unit is nanoseconds
+		/// \details The timer requires hardware support nanoseconds
+		NANOSECONDS
+	};
+
+	/// \brief Construct a TimerBase
+	/// \param unit the unit of measure
+	/// \param stuckAtZero flag
 	TimerBase(Unit unit, bool stuckAtZero)
 		: m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false)
 		, m_start(0), m_last(0) {}
 
-	virtual TimerWord GetCurrentTimerValue() =0;	// GetCurrentTime is a macro in MSVC 6.0
-	virtual TimerWord TicksPerSecond() =0;	// this is not the resolution, just a conversion factor into seconds
+	/// \brief Retrieve the current timer value
+	/// \return the current timer value
+	virtual TimerWord GetCurrentTimerValue() =0;
 
+	/// \brief Retrieve ticks per second
+	/// \return ticks per second
+	/// \details TicksPerSecond() is not the timer resolution. It is a
+	///  conversion factor into seconds.
+	virtual TimerWord TicksPerSecond() =0;
+
+	/// \brief Start the timer
 	void StartTimer();
+
+	/// \brief Retrieve the elapsed time
+	/// \return the elapsed time as a double
+	/// \details The return value of ElapsedTimeAsDouble() depends upon
+	///  the Unit selected during construction of the timer. For example,
+	///  if <tt>Unit = SECONDS</tt> and ElapsedTimeAsDouble() returns 3,
+	///  then the timer has run for 3 seconds. If
+	///  <tt>Unit = MILLISECONDS</tt> and ElapsedTimeAsDouble() returns
+	///  3000, then the timer has run for 3 seconds.
+	/// \sa Unit, ElapsedTime
 	double ElapsedTimeAsDouble();
+
+	/// \brief Retrieve the elapsed time
+	/// \return the elapsed time as an unsigned long
+	/// \details The return value of ElapsedTime() depends upon the
+	///  Unit selected during construction of the timer. For example, if
+	///  <tt>Unit = SECONDS</tt> and ElapsedTime() returns 3, then
+	///  the timer has run for 3 seconds. If <tt>Unit = MILLISECONDS</tt>
+	///  and ElapsedTime() returns 3000, then the timer has run for 3
+	///  seconds.
+	/// \sa Unit, ElapsedTimeAsDouble
 	unsigned long ElapsedTime();
 
 private:
@@ -39,22 +96,34 @@ private:
 	TimerWord m_start, m_last;
 };
 
-/// \brief Measure CPU time spent executing instructions of this thread (if supported by OS)
-/// \note ThreadUserTimer only works correctly on Windows NT or later desktops and servers.
-/// On Unix-based it reports process time. On Windows Phone and Windows Store it reports wall
-/// clock time with performance counter precision. On all others it reports wall clock time.
+/// \brief Measure CPU time spent executing instructions of this thread
+/// \details ThreadUserTimer requires support of the OS. On Unix-based it
+///  reports process time. On Windows NT or later desktops and servers it
+///  reports thread times with performance counter precision.. On Windows
+///  Phone and Windows Store it reports wall clock time with performance
+///  counter precision. On all others it reports wall clock time.
+/// \note ThreadUserTimer only works correctly on Windows NT or later
+///  desktops and servers.
+/// \sa Timer
 class ThreadUserTimer : public TimerBase
 {
 public:
+	/// \brief Construct a ThreadUserTimer
+	/// \param unit the unit of measure
+	/// \param stuckAtZero flag
 	ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
 	TimerWord GetCurrentTimerValue();
 	TimerWord TicksPerSecond();
 };
 
-/// high resolution timer
+/// \brief High resolution timer
+/// \sa ThreadUserTimer
 class CRYPTOPP_DLL Timer : public TimerBase
 {
 public:
+	/// \brief Construct a Timer
+	/// \param unit the unit of measure
+	/// \param stuckAtZero flag
 	Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false)	: TimerBase(unit, stuckAtZero) {}
 	TimerWord GetCurrentTimerValue();
 	TimerWord TicksPerSecond();

+ 5 - 3
include/cryptlib/ida.h

@@ -11,6 +11,7 @@
 #include "filters.h"
 #include "channels.h"
 #include "secblock.h"
+#include "gf2_32.h"
 #include "stdcpp.h"
 #include "misc.h"
 
@@ -22,7 +23,7 @@ class RawIDA : public AutoSignaling<Unflushable<Multichannel<Filter> > >
 {
 public:
 	RawIDA(BufferedTransformation *attachment=NULLPTR)
-		: m_threshold (0), m_channelsReady(0), m_channelsFinished(0)
+		: m_channelsReady(0), m_channelsFinished(0), m_threshold (0)
 			{Detach(attachment);}
 
 	unsigned int GetThreshold() const {return m_threshold;}
@@ -56,10 +57,11 @@ protected:
 	std::vector<word32> m_inputChannelIds, m_outputChannelIds, m_outputToInput;
 	std::vector<std::string> m_outputChannelIdStrings;
 	std::vector<ByteQueue> m_outputQueues;
-	int m_threshold;
-	unsigned int m_channelsReady, m_channelsFinished;
 	std::vector<SecBlock<word32> > m_v;
 	SecBlock<word32> m_u, m_w, m_y;
+	const GF2_32 m_gf32;
+	unsigned int m_channelsReady, m_channelsFinished;
+	int m_threshold;
 };
 
 /// \brief Shamir's Secret Sharing Algorithm

+ 197 - 172
include/cryptlib/integer.h

@@ -3,14 +3,14 @@
 /// \file integer.h
 /// \brief Multiple precision integer with arithmetic operations
 /// \details The Integer class can represent positive and negative integers
-///   with absolute value less than (256**sizeof(word))<sup>(256**sizeof(int))</sup>.
+///  with absolute value less than (256**sizeof(word))<sup>(256**sizeof(int))</sup>.
 /// \details Internally, the library uses a sign magnitude representation, and the class
-///   has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
-///   used to hold the representation. The second is a Sign (an enumeration), and it is
-///   used to track the sign of the Integer.
+///  has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
+///  used to hold the representation. The second is a Sign (an enumeration), and it is
+///  used to track the sign of the Integer.
 /// \details For details on how the Integer class initializes its function pointers using
-///   InitializeInteger and how it creates Integer::Zero(), Integer::One(), and
-///   Integer::Two(), then see the comments at the top of <tt>integer.cpp</tt>.
+///  InitializeInteger and how it creates Integer::Zero(), Integer::One(), and
+///  Integer::Two(), then see the comments at the top of <tt>integer.cpp</tt>.
 /// \since Crypto++ 1.0
 
 #ifndef CRYPTOPP_INTEGER_H
@@ -36,14 +36,14 @@ typedef SecBlock<word, AllocatorWithCleanup<word, true> > IntegerSecBlock;
 
 /// \brief Multiple precision integer with arithmetic operations
 /// \details The Integer class can represent positive and negative integers
-///   with absolute value less than (256**sizeof(word))<sup>(256**sizeof(int))</sup>.
+///  with absolute value less than (256**sizeof(word))<sup>(256**sizeof(int))</sup>.
 /// \details Internally, the library uses a sign magnitude representation, and the class
-///   has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
-///   used to hold the representation. The second is a Sign (an enumeration), and it is
-///   used to track the sign of the Integer.
+///  has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
+///  used to hold the representation. The second is a Sign (an enumeration), and it is
+///  used to track the sign of the Integer.
 /// \details For details on how the Integer class initializes its function pointers using
-///   InitializeInteger and how it creates Integer::Zero(), Integer::One(), and
-///   Integer::Two(), then see the comments at the top of <tt>integer.cpp</tt>.
+///  InitializeInteger and how it creates Integer::Zero(), Integer::One(), and
+///  Integer::Two(), then see the comments at the top of <tt>integer.cpp</tt>.
 /// \since Crypto++ 1.0
 /// \nosubgrouping
 class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object
@@ -59,7 +59,7 @@ public:
 		};
 
 		/// \brief Exception thrown when a random number cannot be found that
-		///   satisfies the condition
+		///  satisfies the condition
 		class RandomNumberNotFound : public Exception
 		{
 		public:
@@ -120,19 +120,21 @@ public:
 		/// \brief Convert from a C-string
 		/// \param str C-string value
 		/// \param order the ByteOrder of the string to be processed
-		/// \details \p str can be in base 2, 8, 10, or 16. Base is determined by a case
-		///   insensitive suffix of 'h', 'o', or 'b'.  No suffix means base 10.
+		/// \details \p str can be in base 8, 10, or 16. Base is determined
+		///  by a case insensitive suffix of 'o' (8), '.' (10), or 'h' (16).
+		///  No suffix means base 10.
 		/// \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
-		///   integers with curve25519, Poly1305 and Microsoft CAPI.
+		///  integers with curve25519, Poly1305 and Microsoft CAPI.
 		explicit Integer(const char *str, ByteOrder order = BIG_ENDIAN_ORDER);
 
 		/// \brief Convert from a wide C-string
 		/// \param str wide C-string value
 		/// \param order the ByteOrder of the string to be processed
-		/// \details \p str can be in base 2, 8, 10, or 16. Base is determined by a case
-		///   insensitive suffix of 'h', 'o', or 'b'.  No suffix means base 10.
+		/// \details \p str can be in base 8, 10, or 16. Base is determined
+		///  by a case insensitive suffix of 'o' (8), '.' (10), or 'h' (16).
+		///  No suffix means base 10.
 		/// \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
-		///   integers with curve25519, Poly1305 and Microsoft CAPI.
+		///  integers with curve25519, Poly1305 and Microsoft CAPI.
 		explicit Integer(const wchar_t *str, ByteOrder order = BIG_ENDIAN_ORDER);
 
 		/// \brief Convert from a big-endian byte array
@@ -141,7 +143,7 @@ public:
 		/// \param sign enumeration indicating Signedness
 		/// \param order the ByteOrder of the array to be processed
 		/// \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
-		///   integers with curve25519, Poly1305 and Microsoft CAPI.
+		///  integers with curve25519, Poly1305 and Microsoft CAPI.
 		Integer(const byte *encodedInteger, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER);
 
 		/// \brief Convert from a big-endian array
@@ -150,7 +152,7 @@ public:
 		/// \param sign enumeration indicating Signedness
 		/// \param order the ByteOrder of the data to be processed
 		/// \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
-		///   integers with curve25519, Poly1305 and Microsoft CAPI.
+		///  integers with curve25519, Poly1305 and Microsoft CAPI.
 		Integer(BufferedTransformation &bt, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER);
 
 		/// \brief Convert from a BER encoded byte array
@@ -164,15 +166,15 @@ public:
 		Integer(RandomNumberGenerator &rng, size_t bitCount);
 
 		/// \brief Integer representing 0
-		/// \returns an Integer representing 0
+		/// \return an Integer representing 0
 		/// \details Zero() avoids calling constructors for frequently used integers
 		static const Integer & CRYPTOPP_API Zero();
 		/// \brief Integer representing 1
-		/// \returns an Integer representing 1
+		/// \return an Integer representing 1
 		/// \details One() avoids calling constructors for frequently used integers
 		static const Integer & CRYPTOPP_API One();
 		/// \brief Integer representing 2
-		/// \returns an Integer representing 2
+		/// \return an Integer representing 2
 		/// \details Two() avoids calling constructors for frequently used integers
 		static const Integer & CRYPTOPP_API Two();
 
@@ -185,17 +187,17 @@ public:
 		/// \param mod the modulus used to reduce the equivalence class
 		/// \throw RandomNumberNotFound if the set is empty.
 		/// \details Ideally, the random integer created should be uniformly distributed
-		///   over <tt>{x | min \<= x \<= max</tt> and \p x is of rnType and <tt>x \% mod == equiv}</tt>.
-		///   However the actual distribution may not be uniform because sequential
-		///   search is used to find an appropriate number from a random starting
-		///   point.
+		///  over <tt>{x | min \<= x \<= max</tt> and \p x is of rnType and <tt>x \% mod == equiv}</tt>.
+		///  However the actual distribution may not be uniform because sequential
+		///  search is used to find an appropriate number from a random starting
+		///  point.
 		/// \details May return (with very small probability) a pseudoprime when a prime
-		///   is requested and <tt>max \> lastSmallPrime*lastSmallPrime</tt>. \p lastSmallPrime
-		///   is declared in nbtheory.h.
+		///  is requested and <tt>max \> lastSmallPrime*lastSmallPrime</tt>. \p lastSmallPrime
+		///  is declared in nbtheory.h.
 		Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One());
 
 		/// \brief Exponentiates to a power of 2
-		/// \returns the Integer 2<sup>e</sup>
+		/// \return the Integer 2<sup>e</sup>
 		/// \sa a_times_b_mod_c() and a_exp_b_mod_c()
 		static Integer CRYPTOPP_API Power2(size_t e);
 	//@}
@@ -213,7 +215,7 @@ public:
 		/// \param sign enumeration indicating Signedness
 		/// \details Unsigned means encode absolute value, signed means encode two's complement if negative.
 		/// \details outputLen can be used to ensure an Integer is encoded to an exact size (rather than a
-		///   minimum size). An exact size is useful, for example, when encoding to a field element size.
+		///  minimum size). An exact size is useful, for example, when encoding to a field element size.
 		void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const;
 
 		/// \brief Encode in big-endian format
@@ -222,13 +224,13 @@ public:
 		/// \param sign enumeration indicating Signedness
 		/// \details Unsigned means encode absolute value, signed means encode two's complement if negative.
 		/// \details outputLen can be used to ensure an Integer is encoded to an exact size (rather than a
-		///   minimum size). An exact size is useful, for example, when encoding to a field element size.
+		///  minimum size). An exact size is useful, for example, when encoding to a field element size.
 		void Encode(BufferedTransformation &bt, size_t outputLen, Signedness sign=UNSIGNED) const;
 
 		/// \brief Encode in DER format
 		/// \param bt BufferedTransformation object
 		/// \details Encodes the Integer using Distinguished Encoding Rules
-		///   The result is placed into a BufferedTransformation object
+		///  The result is placed into a BufferedTransformation object
 		void DEREncode(BufferedTransformation &bt) const;
 
 		/// \brief Encode absolute value as big-endian octet string
@@ -239,16 +241,16 @@ public:
 		/// \brief Encode absolute value in OpenPGP format
 		/// \param output big-endian byte array
 		/// \param bufferSize length of the byte array
-		/// \returns length of the output
+		/// \return length of the output
 		/// \details OpenPGPEncode places result into the buffer and returns the
-		///   number of bytes used for the encoding
+		///  number of bytes used for the encoding
 		size_t OpenPGPEncode(byte *output, size_t bufferSize) const;
 
 		/// \brief Encode absolute value in OpenPGP format
 		/// \param bt BufferedTransformation object
-		/// \returns length of the output
+		/// \return length of the output
 		/// \details OpenPGPEncode places result into a BufferedTransformation object and returns the
-		///   number of bytes used for the encoding
+		///  number of bytes used for the encoding
 		size_t OpenPGPEncode(BufferedTransformation &bt) const;
 
 		/// \brief Decode from big-endian byte array
@@ -297,7 +299,7 @@ public:
 	/// \name ACCESSORS
 	//@{
 		/// \brief Determines if the Integer is convertable to Long
-		/// \returns true if *this can be represented as a signed long
+		/// \return true if <tt>*this</tt> can be represented as a signed long
 		/// \sa ConvertToLong()
 		bool IsConvertableToLong() const;
 		/// \brief Convert the Integer to Long
@@ -306,113 +308,135 @@ public:
 		signed long ConvertToLong() const;
 
 		/// \brief Determines the number of bits required to represent the Integer
-		/// \returns number of significant bits = floor(log2(abs(*this))) + 1
+		/// \return number of significant bits
+		/// \details BitCount is calculated as <tt>floor(log2(abs(*this))) + 1</tt>.
 		unsigned int BitCount() const;
 		/// \brief Determines the number of bytes required to represent the Integer
-		/// \returns number of significant bytes = ceiling(BitCount()/8)
+		/// \return number of significant bytes
+		/// \details ByteCount is calculated as <tt>ceiling(BitCount()/8)</tt>.
 		unsigned int ByteCount() const;
 		/// \brief Determines the number of words required to represent the Integer
-		/// \returns number of significant words = ceiling(ByteCount()/sizeof(word))
+		/// \return number of significant words
+		/// \details WordCount is calculated as <tt>ceiling(ByteCount()/sizeof(word))</tt>.
 		unsigned int WordCount() const;
 
 		/// \brief Provides the i-th bit of the Integer
-		/// \returns the i-th bit, i=0 being the least significant bit
+		/// \return the i-th bit, i=0 being the least significant bit
 		bool GetBit(size_t i) const;
 		/// \brief Provides the i-th byte of the Integer
-		/// \returns the i-th byte
+		/// \return the i-th byte
 		byte GetByte(size_t i) const;
 		/// \brief Provides the low order bits of the Integer
-		/// \returns n lowest bits of *this >> i
+		/// \return n lowest bits of <tt>*this >> i</tt>
 		lword GetBits(size_t i, size_t n) const;
 
 		/// \brief Determines if the Integer is 0
-		/// \returns true if the Integer is 0, false otherwise
+		/// \return true if the Integer is 0, false otherwise
 		bool IsZero() const {return !*this;}
 		/// \brief Determines if the Integer is non-0
-		/// \returns true if the Integer is non-0, false otherwise
+		/// \return true if the Integer is non-0, false otherwise
 		bool NotZero() const {return !IsZero();}
 		/// \brief Determines if the Integer is negative
-		/// \returns true if the Integer is negative, false otherwise
+		/// \return true if the Integer is negative, false otherwise
 		bool IsNegative() const {return sign == NEGATIVE;}
 		/// \brief Determines if the Integer is non-negative
-		/// \returns true if the Integer is non-negative, false otherwise
+		/// \return true if the Integer is non-negative, false otherwise
 		bool NotNegative() const {return !IsNegative();}
 		/// \brief Determines if the Integer is positive
-		/// \returns true if the Integer is positive, false otherwise
+		/// \return true if the Integer is positive, false otherwise
 		bool IsPositive() const {return NotNegative() && NotZero();}
 		/// \brief Determines if the Integer is non-positive
-		/// \returns true if the Integer is non-positive, false otherwise
+		/// \return true if the Integer is non-positive, false otherwise
 		bool NotPositive() const {return !IsPositive();}
 		/// \brief Determines if the Integer is even parity
-		/// \returns true if the Integer is even, false otherwise
+		/// \return true if the Integer is even, false otherwise
 		bool IsEven() const {return GetBit(0) == 0;}
 		/// \brief Determines if the Integer is odd parity
-		/// \returns true if the Integer is odd, false otherwise
+		/// \return true if the Integer is odd, false otherwise
 		bool IsOdd() const	{return GetBit(0) == 1;}
 	//@}
 
 	/// \name MANIPULATORS
 	//@{
 		/// \brief Assignment
+		/// \param t the other Integer
+		/// \return the result of assignment
 		Integer&  operator=(const Integer& t);
-
 		/// \brief Addition Assignment
+		/// \param t the other Integer
+		/// \return the result of <tt>*this + t</tt>
 		Integer&  operator+=(const Integer& t);
 		/// \brief Subtraction Assignment
+		/// \param t the other Integer
+		/// \return the result of <tt>*this - t</tt>
 		Integer&  operator-=(const Integer& t);
 		/// \brief Multiplication Assignment
+		/// \param t the other Integer
+		/// \return the result of <tt>*this * t</tt>
 		/// \sa a_times_b_mod_c() and a_exp_b_mod_c()
 		Integer&  operator*=(const Integer& t)	{return *this = Times(t);}
 		/// \brief Division Assignment
+		/// \param t the other Integer
+		/// \return the result of <tt>*this / t</tt>
 		Integer&  operator/=(const Integer& t)	{return *this = DividedBy(t);}
 		/// \brief Remainder Assignment
+		/// \param t the other Integer
+		/// \return the result of <tt>*this % t</tt>
 		/// \sa a_times_b_mod_c() and a_exp_b_mod_c()
 		Integer&  operator%=(const Integer& t)	{return *this = Modulo(t);}
 		/// \brief Division Assignment
+		/// \param t the other word
+		/// \return the result of <tt>*this / t</tt>
 		Integer&  operator/=(word t)  {return *this = DividedBy(t);}
 		/// \brief Remainder Assignment
+		/// \param t the other word
+		/// \return the result of <tt>*this % t</tt>
 		/// \sa a_times_b_mod_c() and a_exp_b_mod_c()
 		Integer&  operator%=(word t)  {return *this = Integer(POSITIVE, 0, Modulo(t));}
 
 		/// \brief Left-shift Assignment
+		/// \param n number of bits to shift
+		/// \return reference to this Integer
 		Integer&  operator<<=(size_t n);
 		/// \brief Right-shift Assignment
+		/// \param n number of bits to shift
+		/// \return reference to this Integer
 		Integer&  operator>>=(size_t n);
 
 		/// \brief Bitwise AND Assignment
 		/// \param t the other Integer
-		/// \returns the result of *this & t
-		/// \details operator&=() performs a bitwise AND on *this. Missing bits are truncated
-		///   at the most significant bit positions, so the result is as small as the
-		///   smaller of the operands.
+		/// \return the result of <tt>*this & t</tt>
+		/// \details operator&=() performs a bitwise AND on <tt>*this</tt>. Missing bits are truncated
+		///  at the most significant bit positions, so the result is as small as the
+		///  smaller of the operands.
 		/// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-		///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-		///   the integer should be converted to a 2's compliment representation before performing
-		///   the operation.
+		///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+		///  the integer should be converted to a 2's compliment representation before performing
+		///  the operation.
 		/// \since Crypto++ 6.0
 		Integer& operator&=(const Integer& t);
 		/// \brief Bitwise OR Assignment
 		/// \param t the second Integer
-		/// \returns the result of *this | t
-		/// \details operator|=() performs a bitwise OR on *this. Missing bits are shifted in
-		///   at the most significant bit positions, so the result is as large as the
-		///   larger of the operands.
+		/// \return the result of <tt>*this | t</tt>
+		/// \details operator|=() performs a bitwise OR on <tt>*this</tt>. Missing bits are shifted in
+		///  at the most significant bit positions, so the result is as large as the
+		///  larger of the operands.
 		/// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-		///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-		///   the integer should be converted to a 2's compliment representation before performing
-		///   the operation.
+		///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+		///  the integer should be converted to a 2's compliment representation before performing
+		///  the operation.
 		/// \since Crypto++ 6.0
 		Integer& operator|=(const Integer& t);
 		/// \brief Bitwise XOR Assignment
 		/// \param t the other Integer
-		/// \returns the result of *this ^ t
-		/// \details operator^=() performs a bitwise XOR on *this. Missing bits are shifted
-		///   in at the most significant bit positions, so the result is as large as the
-		///   larger of the operands.
+		/// \return the result of <tt>*this ^ t</tt>
+		/// \details operator^=() performs a bitwise XOR on <tt>*this</tt>. Missing bits are shifted
+		///  in at the most significant bit positions, so the result is as large as the
+		///  larger of the operands.
 		/// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-		///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-		///   the integer should be converted to a 2's compliment representation before performing
-		///   the operation.
+		///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+		///  the integer should be converted to a 2's compliment representation before performing
+		///  the operation.
 		/// \since Crypto++ 6.0
 		Integer& operator^=(const Integer& t);
 
@@ -420,6 +444,7 @@ public:
 		/// \param rng RandomNumberGenerator used to generate material
 		/// \param bitCount the number of bits in the resulting integer
 		/// \details The random integer created is uniformly distributed over <tt>[0, 2<sup>bitCount</sup>]</tt>.
+		/// \note If \p bitCount is 0, then this Integer is set to 0 (and not 0 or 1).
 		void Randomize(RandomNumberGenerator &rng, size_t bitCount);
 
 		/// \brief Set this Integer to random integer
@@ -438,30 +463,30 @@ public:
 		/// \param mod the modulus used to reduce the equivalence class
 		/// \throw RandomNumberNotFound if the set is empty.
 		/// \details Ideally, the random integer created should be uniformly distributed
-		///   over <tt>{x | min \<= x \<= max</tt> and \p x is of rnType and <tt>x \% mod == equiv}</tt>.
-		///   However the actual distribution may not be uniform because sequential
-		///   search is used to find an appropriate number from a random starting
-		///   point.
+		///  over <tt>{x | min \<= x \<= max</tt> and \p x is of rnType and <tt>x \% mod == equiv}</tt>.
+		///  However the actual distribution may not be uniform because sequential
+		///  search is used to find an appropriate number from a random starting
+		///  point.
 		/// \details May return (with very small probability) a pseudoprime when a prime
-		///   is requested and <tt>max \> lastSmallPrime*lastSmallPrime</tt>. \p lastSmallPrime
-		///   is declared in nbtheory.h.
+		///  is requested and <tt>max \> lastSmallPrime*lastSmallPrime</tt>. \p lastSmallPrime
+		///  is declared in nbtheory.h.
 		bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One());
 
 		/// \brief Generate a random number
 		/// \param rng RandomNumberGenerator used to generate material
 		/// \param params additional parameters that cannot be passed directly to the function
-		/// \returns true if a random number was generated, false otherwise
+		/// \return true if a random number was generated, false otherwise
 		/// \details GenerateRandomNoThrow attempts to generate a random number according to the
-		///   parameters specified in params. The function does not throw RandomNumberNotFound.
+		///  parameters specified in params. The function does not throw RandomNumberNotFound.
 		/// \details The example below generates a prime number using NameValuePairs that Integer
-		///   class recognizes. The names are not provided in argnames.h.
+		///  class recognizes. The names are not provided in argnames.h.
 		/// <pre>
-		///     AutoSeededRandomPool prng;
-		///     AlgorithmParameters params = MakeParameters("BitLength", 2048)
-		///                                                ("RandomNumberType", Integer::PRIME);
-		///     Integer x;
-		///     if (x.GenerateRandomNoThrow(prng, params) == false)
-		///         throw std::runtime_error("Failed to generate prime number");
+		///    AutoSeededRandomPool prng;
+		///    AlgorithmParameters params = MakeParameters("BitLength", 2048)
+		///                                               ("RandomNumberType", Integer::PRIME);
+		///    Integer x;
+		///    if (x.GenerateRandomNoThrow(prng, params) == false)
+		///        throw std::runtime_error("Failed to generate prime number");
 		/// </pre>
 		bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs);
 
@@ -470,16 +495,16 @@ public:
 		/// \param params additional parameters that cannot be passed directly to the function
 		/// \throw RandomNumberNotFound if a random number is not found
 		/// \details GenerateRandom attempts to generate a random number according to the
-		///   parameters specified in params.
+		///  parameters specified in params.
 		/// \details The example below generates a prime number using NameValuePairs that Integer
-		///   class recognizes. The names are not provided in argnames.h.
+		///  class recognizes. The names are not provided in argnames.h.
 		/// <pre>
-		///     AutoSeededRandomPool prng;
-		///     AlgorithmParameters params = MakeParameters("BitLength", 2048)
-		///                                                ("RandomNumberType", Integer::PRIME);
-		///     Integer x;
-		///     try { x.GenerateRandom(prng, params); }
-		///     catch (RandomNumberNotFound&) { x = -1; }
+		///    AutoSeededRandomPool prng;
+		///    AlgorithmParameters params = MakeParameters("BitLength", 2048)
+		///                                               ("RandomNumberType", Integer::PRIME);
+		///    Integer x;
+		///    try { x.GenerateRandom(prng, params); }
+		///    catch (RandomNumberNotFound&) { x = -1; }
 		/// </pre>
 		void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs)
 		{
@@ -529,10 +554,10 @@ public:
 	/// \name BINARY OPERATORS
 	//@{
 		/// \brief Perform signed comparison
-		/// \param a the Integer to comapre
-		///   \retval -1 if <tt>*this < a</tt>
-		///   \retval  0 if <tt>*this = a</tt>
-		///   \retval  1 if <tt>*this > a</tt>
+		/// \param a the Integer to compare
+		/// \retval -1 if <tt>*this < a</tt>
+		/// \retval  0 if <tt>*this = a</tt>
+		/// \retval  1 if <tt>*this > a</tt>
 		int Compare(const Integer& a) const;
 
 		/// \brief Addition
@@ -555,40 +580,40 @@ public:
 
 		/// \brief Bitwise AND
 		/// \param t the other Integer
-		/// \returns the result of <tt>*this & t</tt>
+		/// \return the result of <tt>*this & t</tt>
 		/// \details And() performs a bitwise AND on the operands. Missing bits are truncated
-		///   at the most significant bit positions, so the result is as small as the
-		///   smaller of the operands.
+		///  at the most significant bit positions, so the result is as small as the
+		///  smaller of the operands.
 		/// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-		///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-		///   the integer should be converted to a 2's compliment representation before performing
-		///   the operation.
+		///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+		///  the integer should be converted to a 2's compliment representation before performing
+		///  the operation.
 		/// \since Crypto++ 6.0
 		Integer And(const Integer& t) const;
 
 		/// \brief Bitwise OR
 		/// \param t the other Integer
-		/// \returns the result of <tt>*this | t</tt>
+		/// \return the result of <tt>*this | t</tt>
 		/// \details Or() performs a bitwise OR on the operands. Missing bits are shifted in
-		///   at the most significant bit positions, so the result is as large as the
-		///   larger of the operands.
+		///  at the most significant bit positions, so the result is as large as the
+		///  larger of the operands.
 		/// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-		///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-		///   the integer should be converted to a 2's compliment representation before performing
-		///   the operation.
+		///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+		///  the integer should be converted to a 2's compliment representation before performing
+		///  the operation.
 		/// \since Crypto++ 6.0
 		Integer Or(const Integer& t) const;
 
 		/// \brief Bitwise XOR
 		/// \param t the other Integer
-		/// \returns the result of <tt>*this ^ t</tt>
+		/// \return the result of <tt>*this ^ t</tt>
 		/// \details Xor() performs a bitwise XOR on the operands. Missing bits are shifted in
-		///   at the most significant bit positions, so the result is as large as the
-		///   larger of the operands.
+		///  at the most significant bit positions, so the result is as large as the
+		///  larger of the operands.
 		/// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-		///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-		///   the integer should be converted to a 2's compliment representation before performing
-		///   the operation.
+		///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+		///  the integer should be converted to a 2's compliment representation before performing
+		///  the operation.
 		/// \since Crypto++ 6.0
 		Integer Xor(const Integer& t) const;
 
@@ -614,48 +639,48 @@ public:
 		bool IsSquare() const;
 
 		/// \brief Determine if 1 or -1
-		/// \returns true if this integer is 1 or -1, false otherwise
+		/// \return true if this integer is 1 or -1, false otherwise
 		bool IsUnit() const;
 		/// \brief Calculate multiplicative inverse
-		/// \returns MultiplicativeInverse inverse if 1 or -1, otherwise return 0.
+		/// \return MultiplicativeInverse inverse if 1 or -1, otherwise return 0.
 		Integer MultiplicativeInverse() const;
 
 		/// \brief Extended Division
 		/// \param r a reference for the remainder
 		/// \param q a reference for the quotient
-		/// \param a a reference to the dividend
-		/// \param d a reference to the divisor
+		/// \param a reference to the dividend
+		/// \param d reference to the divisor
 		/// \details Divide calculates r and q such that (a == d*q + r) && (0 <= r < abs(d)).
 		static void CRYPTOPP_API Divide(Integer &r, Integer &q, const Integer &a, const Integer &d);
 
 		/// \brief Extended Division
 		/// \param r a reference for the remainder
 		/// \param q a reference for the quotient
-		/// \param a a reference to the dividend
-		/// \param d a reference to the divisor
+		/// \param a reference to the dividend
+		/// \param d reference to the divisor
 		/// \details Divide calculates r and q such that (a == d*q + r) && (0 <= r < abs(d)).
-		///   This overload uses a faster division algorithm because the divisor is short.
+		///  This overload uses a faster division algorithm because the divisor is short.
 		static void CRYPTOPP_API Divide(word &r, Integer &q, const Integer &a, word d);
 
 		/// \brief Extended Division
 		/// \param r a reference for the remainder
 		/// \param q a reference for the quotient
-		/// \param a a reference to the dividend
-		/// \param n a reference to the divisor
+		/// \param a reference to the dividend
+		/// \param n reference to the divisor
 		/// \details DivideByPowerOf2 calculates r and q such that (a == d*q + r) && (0 <= r < abs(d)).
-		///   It returns same result as Divide(r, q, a, Power2(n)), but faster.
-		///   This overload uses a faster division algorithm because the divisor is a power of 2.
+		///  It returns same result as Divide(r, q, a, Power2(n)), but faster.
+		///  This overload uses a faster division algorithm because the divisor is a power of 2.
 		static void CRYPTOPP_API DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n);
 
 		/// \brief Calculate greatest common divisor
-		/// \param a a reference to the first number
-		/// \param n a reference to the secind number
-		/// \returns the greatest common divisor <tt>a</tt> and <tt>n</tt>.
+		/// \param a reference to the first number
+		/// \param n reference to the secind number
+		/// \return the greatest common divisor <tt>a</tt> and <tt>n</tt>.
 		static Integer CRYPTOPP_API Gcd(const Integer &a, const Integer &n);
 
 		/// \brief Calculate multiplicative inverse
-		/// \param n a reference to the modulus
-		/// \returns an Integer <tt>*this % n</tt>.
+		/// \param n reference to the modulus
+		/// \return an Integer <tt>*this % n</tt>.
 		/// \details InverseMod returns the multiplicative inverse of the Integer <tt>*this</tt>
 		///  modulo the Integer <tt>n</tt>. If no Integer exists then Integer 0 is returned.
 		/// \sa a_times_b_mod_c() and a_exp_b_mod_c()
@@ -663,7 +688,7 @@ public:
 
 		/// \brief Calculate multiplicative inverse
 		/// \param n the modulus
-		/// \returns a word <tt>*this % n</tt>.
+		/// \return a word <tt>*this % n</tt>.
 		/// \details InverseMod returns the multiplicative inverse of the Integer <tt>*this</tt>
 		///  modulo the word <tt>n</tt>. If no Integer exists then word 0 is returned.
 		/// \sa a_times_b_mod_c() and a_exp_b_mod_c()
@@ -673,35 +698,35 @@ public:
 	/// \name INPUT/OUTPUT
 	//@{
 		/// \brief Extraction operator
-		/// \param in a reference to a std::istream
-		/// \param a a reference to an Integer
-		/// \returns a reference to a std::istream reference
+		/// \param in reference to a std::istream
+		/// \param a reference to an Integer
+		/// \return reference to a std::istream reference
 		friend CRYPTOPP_DLL std::istream& CRYPTOPP_API operator>>(std::istream& in, Integer &a);
 
 		/// \brief Insertion operator
-		/// \param out a reference to a std::ostream
+		/// \param out reference to a std::ostream
 		/// \param a a constant reference to an Integer
-		/// \returns a reference to a std::ostream reference
-		/// \details The output integer responds to std::hex, std::oct, std::hex, std::upper and
-		///   std::lower. The output includes the suffix \a \b h (for hex), \a \b . (\a \b dot, for dec)
-		///   and \a \b o (for octal). There is currently no way to suppress the suffix.
+		/// \return reference to a std::ostream reference
+		/// \details The output integer responds to hex, std::oct, std::hex, std::upper and
+		///  std::lower. The output includes the suffix \a h (for hex), \a . (\a dot, for dec)
+		///  and \a o (for octal). There is currently no way to suppress the suffix.
 		/// \details If you want to print an Integer without the suffix or using an arbitrary base, then
-		///   use IntToString<Integer>().
+		///  use IntToString<Integer>().
 		/// \sa IntToString<Integer>
 		friend CRYPTOPP_DLL std::ostream& CRYPTOPP_API operator<<(std::ostream& out, const Integer &a);
 	//@}
 
 	/// \brief Modular multiplication
-	/// \param x a reference to the first term
-	/// \param y a reference to the second term
-	/// \param m a reference to the modulus
-	/// \returns an Integer <tt>(a * b) % m</tt>.
+	/// \param x reference to the first term
+	/// \param y reference to the second term
+	/// \param m reference to the modulus
+	/// \return an Integer <tt>(a * b) % m</tt>.
 	CRYPTOPP_DLL friend Integer CRYPTOPP_API a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m);
 	/// \brief Modular exponentiation
-	/// \param x a reference to the base
-	/// \param e a reference to the exponent
-	/// \param m a reference to the modulus
-	/// \returns an Integer <tt>(a ^ b) % m</tt>.
+	/// \param x reference to the base
+	/// \param e reference to the exponent
+	/// \param m reference to the modulus
+	/// \return an Integer <tt>(a ^ b) % m</tt>.
 	CRYPTOPP_DLL friend Integer CRYPTOPP_API a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m);
 
 protected:
@@ -762,42 +787,42 @@ inline CryptoPP::word    operator%(const CryptoPP::Integer &a, CryptoPP::word b)
 /// \brief Bitwise AND
 /// \param a the first Integer
 /// \param b the second Integer
-/// \returns the result of a & b
+/// \return the result of a & b
 /// \details operator&() performs a bitwise AND on the operands. Missing bits are truncated
-///   at the most significant bit positions, so the result is as small as the
-///   smaller of the operands.
+///  at the most significant bit positions, so the result is as small as the
+///  smaller of the operands.
 /// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-///   the integer should be converted to a 2's compliment representation before performing
-///   the operation.
+///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+///  the integer should be converted to a 2's compliment representation before performing
+///  the operation.
 /// \since Crypto++ 6.0
 inline CryptoPP::Integer operator&(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.And(b);}
 
 /// \brief Bitwise OR
 /// \param a the first Integer
 /// \param b the second Integer
-/// \returns the result of a | b
+/// \return the result of a | b
 /// \details operator|() performs a bitwise OR on the operands. Missing bits are shifted in
-///   at the most significant bit positions, so the result is as large as the
-///   larger of the operands.
+///  at the most significant bit positions, so the result is as large as the
+///  larger of the operands.
 /// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-///   the integer should be converted to a 2's compliment representation before performing
-///   the operation.
+///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+///  the integer should be converted to a 2's compliment representation before performing
+///  the operation.
 /// \since Crypto++ 6.0
 inline CryptoPP::Integer operator|(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Or(b);}
 
 /// \brief Bitwise XOR
 /// \param a the first Integer
 /// \param b the second Integer
-/// \returns the result of a ^ b
+/// \return the result of a ^ b
 /// \details operator^() performs a bitwise XOR on the operands. Missing bits are shifted
-///   in at the most significant bit positions, so the result is as large as the
-///   larger of the operands.
+///  in at the most significant bit positions, so the result is as large as the
+///  larger of the operands.
 /// \details Internally, Crypto++ uses a sign-magnitude representation. The library
-///   does not attempt to interpret bits, and the result is always POSITIVE. If needed,
-///   the integer should be converted to a 2's compliment representation before performing
-///   the operation.
+///  does not attempt to interpret bits, and the result is always POSITIVE. If needed,
+///  the integer should be converted to a 2's compliment representation before performing
+///  the operation.
 /// \since Crypto++ 6.0
 inline CryptoPP::Integer operator^(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Xor(b);}
 

+ 37 - 15
include/cryptlib/iterhash.h

@@ -1,5 +1,8 @@
 // iterhash.h - originally written and placed in the public domain by Wei Dai
 
+/// \file iterhash.h
+/// \brief Base classes for iterated hashes
+
 #ifndef CRYPTOPP_ITERHASH_H
 #define CRYPTOPP_ITERHASH_H
 
@@ -16,10 +19,6 @@
 # endif
 #endif
 
-// GCC cast warning
-#define HashWordPtr(x) ((HashWordType*)(void*)(x))
-#define ConstHashWordPtr(x) ((const HashWordType*)(const void*)(x))
-
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief Exception thrown when trying to hash more data than is allowed by a hash function
@@ -41,6 +40,8 @@ class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE
 public:
 	typedef T HashWordType;
 
+	virtual ~IteratedHashBase() {}
+
 	/// \brief Construct an IteratedHashBase
 	IteratedHashBase() : m_countLo(0), m_countHi(0) {}
 
@@ -78,13 +79,25 @@ public:
 	/// \brief Computes the hash of the current message
 	/// \param digest a pointer to the buffer to receive the hash
 	/// \param digestSize the size of the truncated digest, in bytes
-	/// \details TruncatedFinal() call Final() and then copies digestSize bytes to digest.
+	/// \details TruncatedFinal() calls Final() and then copies digestSize bytes to digest.
 	///   The hash is restarted the hash for the next message.
 	void TruncatedFinal(byte *digest, size_t digestSize);
 
+	/// \brief Retrieve the provider of this algorithm
+	/// \return the algorithm provider
+	/// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI",
+	///    "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE,
+	///    usually indicate a specialized implementation using instructions from a higher
+	///    instruction set architecture (ISA). Future labels may include external hardware
+	///    like a hardware security module (HSM).
+	/// \note  Provider is not universally implemented yet.
+	virtual std::string AlgorithmProvider() const { return "C++"; }
+
 protected:
-	inline T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
-	inline T GetBitCountLo() const {return m_countLo << 3;}
+	inline T GetBitCountHi() const
+		{return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
+	inline T GetBitCountLo() const
+		{return m_countLo << 3;}
 
 	void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
 	virtual void Init() =0;
@@ -92,7 +105,8 @@ protected:
 	virtual ByteOrder GetByteOrder() const =0;
 	virtual void HashEndianCorrectedBlock(const HashWordType *data) =0;
 	virtual size_t HashMultipleBlocks(const T *input, size_t length);
-	void HashBlock(const HashWordType *input) {HashMultipleBlocks(input, this->BlockSize());}
+	void HashBlock(const HashWordType *input)
+		{HashMultipleBlocks(input, this->BlockSize());}
 
 	virtual T* DataBuf() =0;
 	virtual T* StateBuf() =0;
@@ -115,7 +129,7 @@ public:
 	typedef T_Endianness ByteOrderClass;
 	typedef T_HashWordType HashWordType;
 
-	CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize)
+	CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize);
 	// BCB2006 workaround: can't use BLOCKSIZE here
 	CRYPTOPP_COMPILE_ASSERT((T_BlockSize & (T_BlockSize - 1)) == 0);	// blockSize is a power of 2
 
@@ -127,7 +141,7 @@ public:
 	unsigned int BlockSize() const {return T_BlockSize;}
 
 	/// \brief Provides the byte order of the hash
-	/// \returns the byte order of the hash as an enumeration
+	/// \return the byte order of the hash as an enumeration
 	/// \details GetByteOrder() returns <tt>T_Endianness::ToEnum()</tt>.
 	/// \sa ByteOrder()
 	ByteOrder GetByteOrder() const {return T_Endianness::ToEnum();}
@@ -139,12 +153,18 @@ public:
 	/// \details CorrectEndianess() calls ConditionalByteReverse() using <tt>T_Endianness</tt>.
 	inline void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount)
 	{
+		CRYPTOPP_ASSERT(in != NULLPTR);
+		CRYPTOPP_ASSERT(out != NULLPTR);
+		CRYPTOPP_ASSERT(IsAligned<T_HashWordType>(in));
+		CRYPTOPP_ASSERT(IsAligned<T_HashWordType>(out));
+
 		ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount);
 	}
 
 protected:
+	enum { Blocks = T_BlockSize/sizeof(T_HashWordType) };
 	T_HashWordType* DataBuf() {return this->m_data;}
-	FixedSizeSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType)> m_data;
+	FixedSizeSecBlock<T_HashWordType, Blocks> m_data;
 };
 
 /// \brief Iterated hash with a static transformation function
@@ -161,22 +181,24 @@ class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform
 	: public ClonableImpl<T_Transform, AlgorithmImpl<IteratedHash<T_HashWordType, T_Endianness, T_BlockSize>, T_Transform> >
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize)
+	CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize);
 
 	virtual ~IteratedHashWithStaticTransform() {}
 
 	/// \brief Provides the digest size of the hash
 	/// \return the digest size of the hash, in bytes
 	/// \details DigestSize() returns <tt>DIGESTSIZE</tt>.
-	unsigned int DigestSize() const {return DIGESTSIZE;};
+	unsigned int DigestSize() const {return DIGESTSIZE;}
 
 protected:
-	IteratedHashWithStaticTransform() {this->Init();}
+	// https://github.com/weidai11/cryptopp/issues/147#issuecomment-766231864
+	IteratedHashWithStaticTransform() {IteratedHashWithStaticTransform::Init();}
 	void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);}
 	void Init() {T_Transform::InitState(this->m_state);}
 
+	enum { Blocks = T_BlockSize/sizeof(T_HashWordType) };
 	T_HashWordType* StateBuf() {return this->m_state;}
-	FixedSizeAlignedSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType), T_StateAligned> m_state;
+	FixedSizeAlignedSecBlock<T_HashWordType, Blocks, T_StateAligned> m_state;
 };
 
 #if !defined(__GNUC__) && !defined(__clang__)

+ 6 - 6
include/cryptlib/kalyna.h

@@ -106,8 +106,8 @@ public:
     protected:
         void SetKey_22(const word64 key[2]);
         void SetKey_24(const word64 key[4]);
-        void ProcessBlock_22(const word64 inBlock[2], const word64 xorBlock[2], word64 outBlock[2]) const;
-        void ProcessBlock_24(const word64 inBlock[2], const word64 xorBlock[2] ,word64 outBlock[2]) const;
+        void ProcessBlock_22(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+        void ProcessBlock_24(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
     };
 
     typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
@@ -152,8 +152,8 @@ public:
     protected:
         void SetKey_44(const word64 key[4]);
         void SetKey_48(const word64 key[8]);
-        void ProcessBlock_44(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const;
-        void ProcessBlock_48(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const;
+        void ProcessBlock_44(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+        void ProcessBlock_48(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
     };
 
     typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
@@ -163,7 +163,7 @@ public:
 /// \brief Kalyna 512-bit block cipher
 /// \details Kalyna512 provides 512-bit block size. The valid key size is 512-bit.
 /// \since Crypto++ 6.0
-class Kalyna512 : Kalyna512_Info, public BlockCipherDocumentation
+class Kalyna512 : public Kalyna512_Info, public BlockCipherDocumentation
 {
 public:
     class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl<Kalyna512_Info>
@@ -197,7 +197,7 @@ public:
 
     protected:
         void SetKey_88(const word64 key[8]);
-        void ProcessBlock_88(const word64 inBlock[8], const word64 xorBlock[8], word64 outBlock[8]) const;
+        void ProcessBlock_88(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
     };
 
     typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;

+ 47 - 34
include/cryptlib/keccak.h

@@ -26,11 +26,11 @@ NAMESPACE_BEGIN(CryptoPP)
 /// \details Keccak will likely change in the future to accommodate extensibility of the
 ///   round function and the XOF functions.
 /// \details Perform the following to specify a different digest size. The class will use F1600,
-///   XOF d=0x01, and a new vaue for <tt>r()</tt> (which will be <tt>200-2*24 = 152</tt>).
+///   XOF d=0x01, and a new value for <tt>r()</tt> (which will be <tt>200-2*24 = 152</tt>).
 ///   <pre>  Keccack_192 : public Keccack
 ///   {
 ///     public:
-///       CRYPTOPP_CONSTANT(DIGESTSIZE = 24)
+///       CRYPTOPP_CONSTANT(DIGESTSIZE = 24);
 ///       Keccack_192() : Keccack(DIGESTSIZE) {}
 ///   };
 ///   </pre>
@@ -39,30 +39,30 @@ NAMESPACE_BEGIN(CryptoPP)
 /// \since Crypto++ 5.6.4
 class Keccak : public HashTransformation
 {
+protected:
+    /// \brief Construct a Keccak
+    /// \param digestSize the digest size, in bytes
+    /// \details Keccak is the base class for Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
+    ///   Library users should instantiate a derived class, and only use Keccak
+    ///   as a base class reference or pointer.
+    /// \details This constructor was moved to protected at Crypto++ 8.1
+    ///   because users were attempting to create Keccak objects with it.
+    /// \since Crypto++ 5.6.4
+    Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
+
 public:
-	/// \brief Construct a Keccak
-	/// \param digestSize the digest size, in bytes
-	/// \details Keccak is the base class for Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
-	///   Library users should instantiate a derived class, and only use Keccak
-	///   as a base class reference or pointer.
-	/// \since Crypto++ 5.6.4
-	Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
-	unsigned int DigestSize() const {return m_digestSize;}
-	std::string AlgorithmName() const {return "Keccak-" + IntToString(m_digestSize*8);}
-	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "Keccak"; }
-	unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
-
-	void Update(const byte *input, size_t length);
-	void Restart();
-	void TruncatedFinal(byte *hash, size_t size);
-
-	//unsigned int BlockSize() const { return r(); } // that's the idea behind it
+    unsigned int DigestSize() const {return m_digestSize;}
+    unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
+
+    void Update(const byte *input, size_t length);
+    void Restart();
+    void TruncatedFinal(byte *hash, size_t size);
 
 protected:
-	inline unsigned int r() const {return 200 - 2 * m_digestSize;}
+    inline unsigned int r() const {return BlockSize();}
 
-	FixedSizeSecBlock<word64, 25> m_state;
-	unsigned int m_digestSize, m_counter;
+    FixedSizeSecBlock<word64, 25> m_state;
+    unsigned int m_digestSize, m_counter;
 };
 
 /// \brief Keccak message digest template
@@ -72,33 +72,46 @@ template<unsigned int T_DigestSize>
 class Keccak_Final : public Keccak
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
-	CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE)
+    CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize);
+    CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE);
+    static std::string StaticAlgorithmName()
+        { return "Keccak-" + IntToString(DIGESTSIZE * 8); }
+
+    /// \brief Construct a Keccak-X message digest
+    Keccak_Final() : Keccak(DIGESTSIZE) {}
+
+    /// \brief Provides the block size of the compression function
+    /// \return block size of the compression function, in bytes
+    /// \details BlockSize() will return 0 if the hash is not block based
+    ///   or does not have an equivalent block size. For example, Keccak
+    ///   and SHA-3 do not have a block size, but they do have an equivalent
+    ///   block size called rate expressed as <tt>r</tt>.
+    unsigned int BlockSize() const { return BLOCKSIZE; }
+
+    std::string AlgorithmName() const { return StaticAlgorithmName(); }
 
-		/// \brief Construct a Keccak-X message digest
-	Keccak_Final() : Keccak(DIGESTSIZE) {}
-	static std::string StaticAlgorithmName() { return "Keccak-" + IntToString(DIGESTSIZE * 8); }
-	unsigned int BlockSize() const { return BLOCKSIZE; }
 private:
-	CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
-	CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC
+#if !defined(__BORLANDC__)
+    // ensure there was no underflow in the math
+    CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200);
+#endif
 };
 
 /// \brief Keccak-224 message digest
 /// \since Crypto++ 5.6.4
-typedef Keccak_Final<28> Keccak_224;
+DOCUMENTED_TYPEDEF(Keccak_Final<28>, Keccak_224);
 
 /// \brief Keccak-256 message digest
 /// \since Crypto++ 5.6.4
-typedef Keccak_Final<32> Keccak_256;
+DOCUMENTED_TYPEDEF(Keccak_Final<32>, Keccak_256);
 
 /// \brief Keccak-384 message digest
 /// \since Crypto++ 5.6.4
-typedef Keccak_Final<48> Keccak_384;
+DOCUMENTED_TYPEDEF(Keccak_Final<48>, Keccak_384);
 
 /// \brief Keccak-512 message digest
 /// \since Crypto++ 5.6.4
-typedef Keccak_Final<64> Keccak_512;
+DOCUMENTED_TYPEDEF(Keccak_Final<64>, Keccak_512);
 
 NAMESPACE_END
 

+ 108 - 0
include/cryptlib/lea.h

@@ -0,0 +1,108 @@
+// lea.h - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton
+//         Based on "LEA: A 128-Bit Block Cipher for Fast Encryption on Common
+//         Processors" by Deukjo Hong, Jung-Keun Lee, Dong-Chan Kim, Daesung Kwon,
+//         Kwon Ho Ryu, and Dong-Geon Lee.
+
+/// \file lea.h
+/// \brief Classes for the LEA block cipher
+/// \since Crypto++ 8.0
+
+#ifndef CRYPTOPP_LEA_H
+#define CRYPTOPP_LEA_H
+
+#include "config.h"
+#include "seckey.h"
+#include "secblock.h"
+#include "algparam.h"
+
+#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
+# ifndef CRYPTOPP_DISABLE_LEA_SIMD
+#  define CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS 1
+# endif
+#endif
+
+// Yet another SunStudio/SunCC workaround. Failed self tests
+// in SSE code paths on i386 for SunStudio 12.3 and below.
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x5120)
+# undef CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief LEA block cipher information
+/// \since Crypto++ 8.0
+struct LEA_Info : public FixedBlockSize<16>, public VariableKeyLength<16,16,32,8>
+{
+    /// \brief The algorithm name
+    /// \return the algorithm name
+    /// \details StaticAlgorithmName returns the algorithm's name as a static
+    ///   member function.
+    static const std::string StaticAlgorithmName()
+    {
+        // Format is Cipher-Blocksize
+        return "LEA-128";
+    }
+};
+
+/// \brief LEA 128-bit block cipher
+/// \details LEA provides 128-bit block size. The valid key size is 128-bits, 192-bits and 256-bits.
+/// \note Crypto++ provides a byte oriented implementation
+/// \sa <a href="http://www.cryptopp.com/wiki/LEA">LEA</a>,
+///   <a href="https://seed.kisa.or.kr/html/egovframework/iwt/ds/ko/ref/LEA%20A%20128-Bit%20Block%20Cipher%20for%20Fast%20Encryption%20on%20Common%20Processors-English.pdf">
+///   LEA: A 128-Bit Block Cipher for Fast Encryption on Common Processors</a>
+/// \since Crypto++ 8.0
+class CRYPTOPP_NO_VTABLE LEA : public LEA_Info, public BlockCipherDocumentation
+{
+public:
+    /// \brief LEA block cipher transformation functions
+    /// \details Provides implementation common to encryption and decryption
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<LEA_Info>
+    {
+    protected:
+        void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
+        std::string AlgorithmProvider() const;
+
+        SecBlock<word32> m_rkey;
+        mutable SecBlock<word32> m_temp;
+        unsigned int m_rounds;
+    };
+
+    /// \brief Encryption transformation
+    /// \details Enc provides implementation for encryption transformation. All key and block
+    ///   sizes are supported.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Enc : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+#if CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS
+        size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
+    };
+
+    /// \brief Decryption transformation
+    /// \details Dec provides implementation for decryption transformation. All key and block
+    ///   sizes are supported.
+    /// \since Crypto++ 8.0
+    class CRYPTOPP_NO_VTABLE Dec : public Base
+    {
+    public:
+        void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+#if CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS
+        size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
+    };
+
+    typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+    typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+typedef LEA::Encryption LEAEncryption;
+typedef LEA::Decryption LEADecryption;
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_LEA_H

+ 262 - 0
include/cryptlib/lsh.h

@@ -0,0 +1,262 @@
+// lsh.h - written and placed in the public domain by Jeffrey Walton
+//         Based on the specification and source code provided by
+//         Korea Internet & Security Agency (KISA) website. Also
+//         see https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do
+//         and https://seed.kisa.or.kr/kisa/Board/22/detailView.do.
+
+// We are hitting some sort of GCC bug in the LSH AVX2 code path.
+// Clang is OK on the AVX2 code path. We believe it is GCC Issue
+// 82735, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. It
+// makes using zeroupper a little tricky.
+
+/// \file lsh.h
+/// \brief Classes for the LSH hash functions
+/// \since Crypto++ 8.6
+/// \sa <A HREF="https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do">LSH</A>
+///  on the Korea Internet & Security Agency (KISA) website.
+#ifndef CRYPTOPP_LSH_H
+#define CRYPTOPP_LSH_H
+
+#include "cryptlib.h"
+#include "secblock.h"
+
+// Enable SSE2 and AVX2 for 64-bit machines.
+// 32-bit machines slow down with SSE2.
+#if (CRYPTOPP_BOOL_X32) || (CRYPTOPP_BOOL_X64)
+# define CRYPTOPP_ENABLE_64BIT_SSE 1
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief LSH-224 and LSH-256 hash base class
+/// \details LSH256_Base is the base class for both LSH-224 and LSH-256
+/// \since Crypto++ 8.6
+class LSH256_Base : public HashTransformation
+{
+public:
+	/// \brief Block size, in bytes
+	/// \details LSH_256 uses LSH256_MSG_BLK_BYTE_LEN for block size, which is 128
+	CRYPTOPP_CONSTANT(BLOCKSIZE = 128);
+
+	virtual ~LSH256_Base() {}
+
+	unsigned int BlockSize() const { return BLOCKSIZE; }
+	unsigned int DigestSize() const { return m_digestSize; }
+	unsigned int OptimalDataAlignment() const { return GetAlignmentOf<word32>(); }
+
+	void Restart();
+	void Update(const byte *input, size_t size);
+	void TruncatedFinal(byte *hash, size_t size);
+
+	std::string AlgorithmProvider() const;
+
+protected:
+	LSH256_Base(unsigned int algType, unsigned int digestSize)
+		: m_digestSize(digestSize) { m_state[80] = algType; }
+
+protected:
+	// Working state is:
+	//   * cv_l = 8 32-bit words
+	//   * cv_r = 8 32-bit words
+	//   * submsg_e_l = 8 32-bit words
+	//   * submsg_e_r = 8 32-bit words
+	//   * submsg_o_l = 8 32-bit words
+	//   * submsg_o_r = 8 32-bit words
+	//   * last_block = 32 32-bit words (128 bytes)
+	//   * algType
+	//   * remainingBitLength
+	FixedSizeSecBlock<word32, 80+2> m_state;
+	// word32 m_algType, m_remainingBitLength;
+	word32 m_digestSize;
+};
+
+/// \brief LSH-224 hash function
+/// \sa <A HREF="https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do">LSH</A>
+///  on the Korea Internet & Security Agency (KISA) website.
+/// \since Crypto++ 8.6
+class LSH224 : public LSH256_Base
+{
+public:
+	/// \brief Digest size, in bytes
+	/// \details LSH_256 uses LSH_GET_HASHBYTE(algType) for digest size, which is 28
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 28);
+	/// \brief Block size, in bytes
+	/// \details LSH_256 uses LSH256_MSG_BLK_BYTE_LEN for block size, which is 128
+	CRYPTOPP_CONSTANT(BLOCKSIZE = LSH256_Base::BLOCKSIZE);
+
+	/// \brief The algorithm's name
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like <tt>AES</tt> or <tt>AES/GCM</tt>.
+	///  Some algorithms do not have standard names yet. For example, there is no standard
+	///  algorithm name for Shoup's ECIES.
+	/// \note StaticAlgorithmName is not universally implemented yet.
+	static std::string StaticAlgorithmName() { return "LSH-224"; }
+
+	/// \brief Construct a LSH-224
+	/// \details LSH_TYPE_224 is the magic value 0x000001C defined in lsh.cpp.
+	LSH224() : LSH256_Base(0x000001C, DIGESTSIZE) { Restart(); }
+
+	std::string AlgorithmName() const { return StaticAlgorithmName(); }
+};
+
+/// \brief LSH-256 hash function
+/// \sa <A HREF="https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do">LSH</A>
+///  on the Korea Internet & Security Agency (KISA) website.
+/// \since Crypto++ 8.6
+class LSH256 : public LSH256_Base
+{
+public:
+	/// \brief Digest size, in bytes
+	/// \details LSH_256 uses LSH_GET_HASHBYTE(algType) for digest size, which is 32
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 32);
+	/// \brief Block size, in bytes
+	/// \details LSH_256 uses LSH256_MSG_BLK_BYTE_LEN for block size, which is 128
+	CRYPTOPP_CONSTANT(BLOCKSIZE = LSH256_Base::BLOCKSIZE);
+
+	/// \brief The algorithm's name
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like <tt>AES</tt> or <tt>AES/GCM</tt>.
+	///  Some algorithms do not have standard names yet. For example, there is no standard
+	///  algorithm name for Shoup's ECIES.
+	/// \note StaticAlgorithmName is not universally implemented yet.
+	static std::string StaticAlgorithmName() { return "LSH-256"; }
+
+	/// \brief Construct a LSH-256
+	/// \details LSH_TYPE_256 is the magic value 0x0000020 defined in lsh.cpp.
+	LSH256() : LSH256_Base(0x0000020, DIGESTSIZE) { Restart(); }
+
+	std::string AlgorithmName() const { return StaticAlgorithmName(); }
+};
+
+/// \brief LSH-384 and LSH-512 hash base class
+/// \details LSH512_Base is the base class for both LSH-384 and LSH-512
+/// \since Crypto++ 8.6
+class LSH512_Base : public HashTransformation
+{
+public:
+	/// \brief Block size, in bytes
+	/// \details LSH_512 uses LSH512_MSG_BLK_BYTE_LEN for block size, which is 256
+	CRYPTOPP_CONSTANT(BLOCKSIZE = 256);
+
+	virtual ~LSH512_Base() {}
+
+	unsigned int BlockSize() const { return BLOCKSIZE; }
+	unsigned int DigestSize() const { return m_digestSize; }
+	unsigned int OptimalDataAlignment() const { return GetAlignmentOf<word64>(); }
+
+	void Restart();
+	void Update(const byte *input, size_t size);
+	void TruncatedFinal(byte *hash, size_t size);
+
+	std::string AlgorithmProvider() const;
+
+protected:
+	LSH512_Base(unsigned int algType, unsigned int digestSize)
+		: m_digestSize(digestSize) { m_state[80] = algType; }
+
+protected:
+	// Working state is:
+	//   * cv_l = 8 64-bit words
+	//   * cv_r = 8 64-bit words
+	//   * submsg_e_l = 8 64-bit words
+	//   * submsg_e_r = 8 64-bit words
+	//   * submsg_o_l = 8 64-bit words
+	//   * submsg_o_r = 8 64-bit words
+	//   * last_block = 32 64-bit words (256 bytes)
+	//   * algType
+	//   * remainingBitLength
+	FixedSizeSecBlock<word64, 80+2> m_state;
+	// word32 m_algType, m_remainingBitLength;
+	word32 m_digestSize;
+};
+
+/// \brief LSH-384 hash function
+/// \sa <A HREF="https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do">LSH</A>
+///  on the Korea Internet & Security Agency (KISA) website.
+/// \since Crypto++ 8.6
+class LSH384 : public LSH512_Base
+{
+public:
+	/// \brief Digest size, in bytes
+	/// \details LSH_512 uses LSH_GET_HASHBYTE(algType) for digest size, which is 48
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 48);
+	/// \brief Block size, in bytes
+	/// \details LSH_512 uses LSH512_MSG_BLK_BYTE_LEN for block size, which is 256
+	CRYPTOPP_CONSTANT(BLOCKSIZE = LSH512_Base::BLOCKSIZE);
+
+	/// \brief The algorithm's name
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like <tt>AES</tt> or <tt>AES/GCM</tt>.
+	///  Some algorithms do not have standard names yet. For example, there is no standard
+	///  algorithm name for Shoup's ECIES.
+	/// \note StaticAlgorithmName is not universally implemented yet.
+	static std::string StaticAlgorithmName() { return "LSH-384"; }
+
+	/// \brief Construct a LSH-384
+	/// \details LSH_TYPE_384 is the magic value 0x0010030 defined in lsh.cpp.
+	LSH384() : LSH512_Base(0x0010030, DIGESTSIZE) { Restart(); }
+
+	std::string AlgorithmName() const { return StaticAlgorithmName(); }
+};
+
+/// \brief LSH-512 hash function
+/// \sa <A HREF="https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do">LSH</A>
+///  on the Korea Internet & Security Agency (KISA) website.
+/// \since Crypto++ 8.6
+class LSH512 : public LSH512_Base
+{
+public:
+	/// \brief Digest size, in bytes
+	/// \details LSH_512 uses LSH_GET_HASHBYTE(algType) for digest size, which is 64
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 64);
+	/// \brief Block size, in bytes
+	/// \details LSH_512 uses LSH512_MSG_BLK_BYTE_LEN for block size, which is 256
+	CRYPTOPP_CONSTANT(BLOCKSIZE = LSH512_Base::BLOCKSIZE);
+
+	/// \brief The algorithm's name
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like <tt>AES</tt> or <tt>AES/GCM</tt>.
+	///  Some algorithms do not have standard names yet. For example, there is no standard
+	///  algorithm name for Shoup's ECIES.
+	/// \note StaticAlgorithmName is not universally implemented yet.
+	static std::string StaticAlgorithmName() { return "LSH-512"; }
+
+	/// \brief Construct a LSH-512
+	/// \details LSH_TYPE_512 is the magic value 0x0010040 defined in lsh.cpp.
+	LSH512() : LSH512_Base(0x0010040, DIGESTSIZE) { Restart(); }
+
+	std::string AlgorithmName() const { return StaticAlgorithmName(); }
+};
+
+/// \brief LSH-512-256 hash function
+/// \sa <A HREF="https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do">LSH</A>
+///  on the Korea Internet & Security Agency (KISA) website.
+/// \since Crypto++ 8.6
+class LSH512_256 : public LSH512_Base
+{
+public:
+	/// \brief Digest size, in bytes
+	/// \details LSH_512 uses LSH_GET_HASHBYTE(algType) for digest size, which is 32
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 32);
+	/// \brief Block size, in bytes
+	/// \details LSH_512 uses LSH512_MSG_BLK_BYTE_LEN for block size, which is 256
+	CRYPTOPP_CONSTANT(BLOCKSIZE = LSH512_Base::BLOCKSIZE);
+
+	/// \brief The algorithm's name
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like <tt>AES</tt> or <tt>AES/GCM</tt>.
+	///  Some algorithms do not have standard names yet. For example, there is no standard
+	///  algorithm name for Shoup's ECIES.
+	/// \note StaticAlgorithmName is not universally implemented yet.
+	static std::string StaticAlgorithmName() { return "LSH-512-256"; }
+
+	/// \brief Construct a LSH-512-256
+	/// \details LSH_TYPE_512_256 is the magic value 0x0010020 defined in lsh.cpp.
+	LSH512_256() : LSH512_Base(0x0010020, DIGESTSIZE) { Restart(); }
+
+	std::string AlgorithmName() const { return StaticAlgorithmName(); }
+};
+
+NAMESPACE_END
+
+#endif  // CRYPTOPP_LSH_H

+ 2 - 2
include/cryptlib/lubyrack.h

@@ -37,7 +37,7 @@ class LR : public LR_Info<T>, public BlockCipherDocumentation
 		}
 
 	protected:
-		CRYPTOPP_CONSTANT(S=T::DIGESTSIZE)
+		CRYPTOPP_CONSTANT(S=T::DIGESTSIZE);
 		unsigned int L;	// key length / 2
 		SecByteBlock key;
 
@@ -115,7 +115,7 @@ class LR : public LR_Info<T>, public BlockCipherDocumentation
 			if (xorBlock)
 				xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
 			else
-				memcpy(outBlock, this->buffer, 2*this->S);
+				std::memcpy(outBlock, this->buffer, 2*this->S);
 		}
 #undef KL
 #undef KR

+ 5 - 3
include/cryptlib/md2.h

@@ -20,15 +20,17 @@ namespace Weak1 {
 class MD2 : public HashTransformation
 {
 public:
+	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "MD2";}
+
 	MD2();
 	void Update(const byte *input, size_t length);
 	void TruncatedFinal(byte *hash, size_t size);
 	unsigned int DigestSize() const {return DIGESTSIZE;}
 	unsigned int BlockSize() const {return BLOCKSIZE;}
-	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "MD2";}
+	std::string AlgorithmName() const {return StaticAlgorithmName();}
 
-	CRYPTOPP_CONSTANT(DIGESTSIZE = 16)
-	CRYPTOPP_CONSTANT(BLOCKSIZE = 16)
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 16);
+	CRYPTOPP_CONSTANT(BLOCKSIZE = 16);
 
 private:
 	void Transform();

+ 48 - 45
include/cryptlib/mersenne.h

@@ -2,8 +2,8 @@
 
 /// \file mersenne.h
 /// \brief Class file for Mersenne Twister
-/// \warning MersenneTwister is suitable for Monte-Carlo simulations, where uniformaly distrubuted
-///   numbers are required quickly. It should not be used for cryptographic purposes.
+/// \warning MersenneTwister is suitable for Monte-Carlo simulations, where uniformaly distributed
+///  numbers are required quickly. It should not be used for cryptographic purposes.
 /// \since Crypto++ 5.6.3
 #ifndef CRYPTOPP_MERSENNE_TWISTER_H
 #define CRYPTOPP_MERSENNE_TWISTER_H
@@ -21,8 +21,10 @@ NAMESPACE_BEGIN(CryptoPP)
 /// \tparam F Multiplier constant
 /// \tparam S Initial seed
 /// \details Provides the MersenneTwister implementation. The class is a header-only implementation.
-/// \warning MersenneTwister is suitable for simulations, where uniformaly distrubuted numbers are
-///   required quickly. It should not be used for cryptographic purposes.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
+/// \warning MersenneTwister is suitable for simulations, where uniformaly distributed numbers are
+///  required quickly. It should not be used for cryptographic purposes.
 /// \sa MT19937, MT19937ar
 /// \since Crypto++ 5.6.3
 template <unsigned int K, unsigned int M, unsigned int N, unsigned int F, word32 S>
@@ -36,8 +38,8 @@ public:
 	/// \brief Construct a Mersenne Twister
 	/// \param seed 32-bit seed
 	/// \details Defaults to template parameter S due to changing algorithm
-	///   parameters over time
-	MersenneTwister(word32 seed = S) : m_seed(seed), m_idx(N)
+	///  parameters over time
+	MersenneTwister(word32 seed = S) : m_idx(N)
 	{
 		Reset(seed);
 	}
@@ -48,61 +50,62 @@ public:
 	/// \param input the entropy to add to the generator
 	/// \param length the size of the input buffer
 	/// \details MersenneTwister uses the first 32-bits of <tt>input</tt> to reseed the
-    ///   generator. If fewer bytes are provided, then the seed is padded with 0's.
+	///  generator. If fewer bytes are provided, then the seed is padded with 0's.
 	void IncorporateEntropy(const byte *input, size_t length)
 	{
-		word32 temp = 0;
-		::memcpy(&temp, input, STDMIN(sizeof(temp), length));
-		Reset(temp);
+		// Handle word32 size blocks
+		FixedSizeSecBlock<word32, 1> temp;
+		temp[0] = 0;
 
-		// Wipe temp
-		SecureWipeArray(&temp, 1);
+		if (length > 4)
+			length = 4;
+
+		for (size_t i=0; i<length; ++i)
+		{
+			temp[0] <<= 8;
+			temp[0] = temp[0] | input[i];
+		}
+
+		Reset(temp[0]);
 	}
 
 	/// \brief Generate random array of bytes
 	/// \param output byte buffer
 	/// \param size length of the buffer, in bytes
 	/// \details Bytes are written to output in big endian order. If output length
-	///   is not a multiple of word32, then unused bytes are not accumulated for subsequent
-	///   calls to GenerateBlock. Rather, the unused tail bytes are discarded, and the
-	///   stream is continued at the next word32 boundary from the state array.
+	///  is not a multiple of word32, then unused bytes are not accumulated for subsequent
+	///  calls to GenerateBlock. Rather, the unused tail bytes are discarded, and the
+	///  stream is continued at the next word32 boundary from the state array.
 	void GenerateBlock(byte *output, size_t size)
 	{
 		// Handle word32 size blocks
-		word32 temp;
+		FixedSizeSecBlock<word32, 1> temp;
 		for (size_t i=0; i < size/4; i++, output += 4)
 		{
-			temp = NextMersenneWord();
-			memcpy(output, &temp, 4);
+			temp[0] = NextMersenneWord();
+			std::memcpy(output, temp+0, 4);
 		}
 
 		// No tail bytes
 		if (size%4 == 0)
-		{
-			// Wipe temp
-			SecureWipeArray(&temp, 1);
 			return;
-		}
 
 		// Handle tail bytes
-		temp = NextMersenneWord();
+		temp[0] = NextMersenneWord();
 		switch (size%4)
 		{
-			case 3: output[2] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 1); /* fall through */
-			case 2: output[1] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 2); /* fall through */
-			case 1: output[0] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 3); break;
+			case 3: output[2] = CRYPTOPP_GET_BYTE_AS_BYTE(temp[0], 1); /* fall through */
+			case 2: output[1] = CRYPTOPP_GET_BYTE_AS_BYTE(temp[0], 2); /* fall through */
+			case 1: output[0] = CRYPTOPP_GET_BYTE_AS_BYTE(temp[0], 3); break;
 
-			default: CRYPTOPP_ASSERT(0); ;;
+			default: CRYPTOPP_ASSERT(0);;
 		}
-
-		// Wipe temp
-		SecureWipeArray(&temp, 1);
 	}
 
 	/// \brief Generate a random 32-bit word in the range min to max, inclusive
-	/// \returns random 32-bit word in the range min to max, inclusive
+	/// \return random 32-bit word in the range min to max, inclusive
 	/// \details If the 32-bit candidate is not within the range, then it is discarded
-	///   and a new candidate is used.
+	///  and a new candidate is used.
 	word32 GenerateWord32(word32 min=0, word32 max=0xffffffffL)
 	{
 		const word32 range = max-min;
@@ -122,9 +125,9 @@ public:
 	/// \brief Generate and discard n bytes
 	/// \param n the number of bytes to discard, rounded up to a <tt>word32</tt> size
 	/// \details If n is not a multiple of <tt>word32</tt>, then unused bytes are
-	///   not accumulated for subsequent calls to GenerateBlock. Rather, the unused
-	///   tail bytes are discarded, and the stream is continued at the next
-	///   <tt>word32</tt> boundary from the state array.
+	///  not accumulated for subsequent calls to GenerateBlock. Rather, the unused
+	///  tail bytes are discarded, and the stream is continued at the next
+	///  <tt>word32</tt> boundary from the state array.
 	void DiscardBytes(size_t n)
 	{
 		for(size_t i=0; i < RoundUpToMultipleOf(n, 4U); i++)
@@ -135,7 +138,6 @@ protected:
 
 	void Reset(word32 seed)
 	{
-		m_seed = seed;
 		m_idx = N;
 
 		m_state[0] = seed;
@@ -144,9 +146,9 @@ protected:
 	}
 
 	/// \brief Returns the next 32-bit word from the state array
-	/// \returns the next 32-bit word from the state array
+	/// \return the next 32-bit word from the state array
 	/// \details fetches the next word frm the state array, performs bit operations on
-	///   it, and then returns the value to the caller.
+	///  it, and then returns the value to the caller.
 	word32 NextMersenneWord()
 	{
 		if (m_idx >= N) { Twist(); }
@@ -160,7 +162,7 @@ protected:
 		return temp ^ (temp >> 18);
 	}
 
-	/// \brief Performs the twist operaton on the state array
+	/// \brief Performs the twist operation on the state array
 	void Twist()
 	{
 		static const word32 magic[2]={0x0UL, K};
@@ -193,16 +195,16 @@ private:
 
 	/// \brief 32-bit word state array of size N
 	FixedSizeSecBlock<word32, N+1> m_state;
-	/// \brief the value used to seed the generator
-	word32 m_seed;
 	/// \brief the current index into the state array
 	word32 m_idx;
 };
 
 /// \brief Original MT19937 generator provided in the ACM paper.
 /// \details MT19937 uses 4537 as default initial seed.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 /// \sa MT19937ar, <A HREF="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">Mersenne twister:
-///   a 623-dimensionally equidistributed uniform pseudo-random number generator</A>
+///  a 623-dimensionally equidistributed uniform pseudo-random number generator</A>
 /// \since Crypto++ 5.6.3
 #if CRYPTOPP_DOXYGEN_PROCESSING
 class MT19937 : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> {};
@@ -212,9 +214,11 @@ typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/,
 
 /// \brief Updated MT19937 generator adapted to provide an array for initialization.
 /// \details MT19937 uses 5489 as default initial seed. Use this generator when interoperating with C++11's
-///   mt19937 class.
+///  mt19937 class.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 /// \sa MT19937, <A HREF="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">Mersenne Twister
-///   with improved initialization</A>
+///  with improved initialization</A>
 /// \since Crypto++ 5.6.3
 #if CRYPTOPP_DOXYGEN_PROCESSING
 class MT19937ar : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> {};
@@ -225,4 +229,3 @@ typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*181243
 NAMESPACE_END
 
 #endif // CRYPTOPP_MERSENNE_TWISTER_H
-

File diff suppressed because it is too large
+ 516 - 163
include/cryptlib/misc.h


+ 58 - 37
include/cryptlib/modarith.h

@@ -26,15 +26,20 @@ CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<Integer>;
 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<Integer>;
 
 /// \brief Ring of congruence classes modulo n
-/// \details This implementation represents each congruence class as the smallest
-///   non-negative integer in that class.
-/// \details <tt>const Element&</tt> returned by member functions are references
-///   to internal data members. Since each object may have only
-///   one such data member for holding results, the following code
-///   will produce incorrect results:
-///   <pre>    abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
-///   But this should be fine:
-///   <pre>    abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
+/// \details This implementation represents each congruence class as
+///  the smallest non-negative integer in that class.
+/// \details <tt>const Element&</tt> returned by member functions are
+///  references to internal data members. Since each object may have
+///  only one such data member for holding results, you should use the
+///  class like this:
+///  <pre>    abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
+///  The following code will produce <i>incorrect</i> results:
+///  <pre>    abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
+/// \details If a ModularArithmetic() is copied or assigned the modulus
+///  is copied, but not the internal data members. The internal data
+///  members are undefined after copy or assignment.
+/// \sa <A HREF="https://cryptopp.com/wiki/Integer">Integer</A> on the
+///  Crypto++ wiki.
 class CRYPTOPP_DLL ModularArithmetic : public AbstractRing<Integer>
 {
 public:
@@ -47,19 +52,30 @@ public:
 	/// \brief Construct a ModularArithmetic
 	/// \param modulus congruence class modulus
 	ModularArithmetic(const Integer &modulus = Integer::One())
-		: AbstractRing<Integer>(), m_modulus(modulus), m_result((word)0, modulus.reg.size()) {}
+		: m_modulus(modulus), m_result(static_cast<word>(0), modulus.reg.size()) {}
 
 	/// \brief Copy construct a ModularArithmetic
 	/// \param ma other ModularArithmetic
 	ModularArithmetic(const ModularArithmetic &ma)
-		: AbstractRing<Integer>(), m_modulus(ma.m_modulus), m_result((word)0, ma.m_modulus.reg.size()) {}
+		: AbstractRing<Integer>(ma), m_modulus(ma.m_modulus), m_result(static_cast<word>(0), m_modulus.reg.size()) {}
+
+	/// \brief Assign a ModularArithmetic
+	/// \param ma other ModularArithmetic
+	ModularArithmetic& operator=(const ModularArithmetic &ma) {
+		if (this != &ma)
+		{
+			m_modulus = ma.m_modulus;
+			m_result = Integer(static_cast<word>(0), m_modulus.reg.size());
+		}
+		return *this;
+	}
 
 	/// \brief Construct a ModularArithmetic
 	/// \param bt BER encoded ModularArithmetic
 	ModularArithmetic(BufferedTransformation &bt);	// construct from BER encoded parameters
 
 	/// \brief Clone a ModularArithmetic
-	/// \returns pointer to a new ModularArithmetic
+	/// \return pointer to a new ModularArithmetic
 	/// \details Clone effectively copy constructs a new ModularArithmetic. The caller is
 	///   responsible for deleting the pointer returned from this method.
 	virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);}
@@ -79,7 +95,7 @@ public:
 	void BERDecodeElement(BufferedTransformation &in, Element &a) const;
 
 	/// \brief Retrieves the modulus
-	/// \returns the modulus
+	/// \return the modulus
 	const Integer& GetModulus() const {return m_modulus;}
 
 	/// \brief Sets the modulus
@@ -88,12 +104,12 @@ public:
 		{m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());}
 
 	/// \brief Retrieves the representation
-	/// \returns true if the if the modulus is in Montgomery form for multiplication, false otherwise
+	/// \return true if the if the modulus is in Montgomery form for multiplication, false otherwise
 	virtual bool IsMontgomeryRepresentation() const {return false;}
 
 	/// \brief Reduces an element in the congruence class
 	/// \param a element to convert
-	/// \returns the reduced element
+	/// \return the reduced element
 	/// \details ConvertIn is useful for derived classes, like MontgomeryRepresentation, which
 	///   must convert between representations.
 	virtual Integer ConvertIn(const Integer &a) const
@@ -101,7 +117,7 @@ public:
 
 	/// \brief Reduces an element in the congruence class
 	/// \param a element to convert
-	/// \returns the reduced element
+	/// \return the reduced element
 	/// \details ConvertOut is useful for derived classes, like MontgomeryRepresentation, which
 	///   must convert between representations.
 	virtual Integer ConvertOut(const Integer &a) const
@@ -114,54 +130,54 @@ public:
 	/// \brief Compare two elements for equality
 	/// \param a first element
 	/// \param b second element
-	/// \returns true if the elements are equal, false otherwise
+	/// \return true if the elements are equal, false otherwise
 	/// \details Equal() tests the elements for equality using <tt>a==b</tt>
 	bool Equal(const Integer &a, const Integer &b) const
 		{return a==b;}
 
 	/// \brief Provides the Identity element
-	/// \returns the Identity element
+	/// \return the Identity element
 	const Integer& Identity() const
 		{return Integer::Zero();}
 
 	/// \brief Adds elements in the ring
 	/// \param a first element
 	/// \param b second element
-	/// \returns the sum of <tt>a</tt> and <tt>b</tt>
+	/// \return the sum of <tt>a</tt> and <tt>b</tt>
 	const Integer& Add(const Integer &a, const Integer &b) const;
 
 	/// \brief TODO
 	/// \param a first element
 	/// \param b second element
-	/// \returns TODO
+	/// \return TODO
 	Integer& Accumulate(Integer &a, const Integer &b) const;
 
 	/// \brief Inverts the element in the ring
 	/// \param a first element
-	/// \returns the inverse of the element
+	/// \return the inverse of the element
 	const Integer& Inverse(const Integer &a) const;
 
 	/// \brief Subtracts elements in the ring
 	/// \param a first element
 	/// \param b second element
-	/// \returns the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
+	/// \return the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
 	const Integer& Subtract(const Integer &a, const Integer &b) const;
 
 	/// \brief TODO
 	/// \param a first element
 	/// \param b second element
-	/// \returns TODO
+	/// \return TODO
 	Integer& Reduce(Integer &a, const Integer &b) const;
 
 	/// \brief Doubles an element in the ring
 	/// \param a the element
-	/// \returns the element doubled
+	/// \return the element doubled
 	/// \details Double returns <tt>Add(a, a)</tt>. The element <tt>a</tt> must provide an Add member function.
 	const Integer& Double(const Integer &a) const
 		{return Add(a, a);}
 
 	/// \brief Retrieves the multiplicative identity
-	/// \returns the multiplicative identity
+	/// \return the multiplicative identity
 	/// \details the base class implementations returns 1.
 	const Integer& MultiplicativeIdentity() const
 		{return Integer::One();}
@@ -169,21 +185,21 @@ public:
 	/// \brief Multiplies elements in the ring
 	/// \param a the multiplicand
 	/// \param b the multiplier
-	/// \returns the product of a and b
+	/// \return the product of a and b
 	/// \details Multiply returns <tt>a*b\%n</tt>.
 	const Integer& Multiply(const Integer &a, const Integer &b) const
 		{return m_result1 = a*b%m_modulus;}
 
 	/// \brief Square an element in the ring
 	/// \param a the element
-	/// \returns the element squared
+	/// \return the element squared
 	/// \details Square returns <tt>a*a\%n</tt>. The element <tt>a</tt> must provide a Square member function.
 	const Integer& Square(const Integer &a) const
 		{return m_result1 = a.Squared()%m_modulus;}
 
 	/// \brief Determines whether an element is a unit in the ring
 	/// \param a the element
-	/// \returns true if the element is a unit after reduction, false otherwise.
+	/// \return true if the element is a unit after reduction, false otherwise.
 	bool IsUnit(const Integer &a) const
 		{return Integer::Gcd(a, m_modulus).IsUnit();}
 
@@ -197,7 +213,7 @@ public:
 	/// \brief Divides elements in the ring
 	/// \param a the dividend
 	/// \param b the divisor
-	/// \returns the quotient
+	/// \return the quotient
 	/// \details Divide returns <tt>a*b<sup>-1</sup>\%n</tt>.
 	const Integer& Divide(const Integer &a, const Integer &b) const
 		{return Multiply(a, MultiplicativeInverse(b));}
@@ -207,7 +223,7 @@ public:
 	/// \param e1 first exponent
 	/// \param y second element
 	/// \param e2 second exponent
-	/// \returns TODO
+	/// \return TODO
 	Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const;
 
 	/// \brief Exponentiates a base to multiple exponents in the ring
@@ -223,23 +239,23 @@ public:
 	void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
 
 	/// \brief Provides the maximum bit size of an element in the ring
-	/// \returns maximum bit size of an element
+	/// \return maximum bit size of an element
 	unsigned int MaxElementBitLength() const
 		{return (m_modulus-1).BitCount();}
 
 	/// \brief Provides the maximum byte size of an element in the ring
-	/// \returns maximum byte size of an element
+	/// \return maximum byte size of an element
 	unsigned int MaxElementByteLength() const
 		{return (m_modulus-1).ByteCount();}
 
 	/// \brief Provides a random element in the ring
 	/// \param rng RandomNumberGenerator used to generate material
 	/// \param ignore_for_now unused
-	/// \returns a random element that is uniformly distributed
+	/// \return a random element that is uniformly distributed
 	/// \details RandomElement constructs a new element in the range <tt>[0,n-1]</tt>, inclusive.
 	///   The element's class must provide a constructor with the signature <tt>Element(RandomNumberGenerator rng,
 	///   Element min, Element max)</tt>.
-	Element RandomElement(RandomNumberGenerator &rng , const RandomizationParameter &ignore_for_now = 0) const
+	Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter &ignore_for_now = 0) const
 		// left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct
 	{
 		CRYPTOPP_UNUSED(ignore_for_now);
@@ -248,12 +264,17 @@ public:
 
 	/// \brief Compares two ModularArithmetic for equality
 	/// \param rhs other ModularArithmetic
-	/// \returns true if this is equal to the other, false otherwise
+	/// \return true if this is equal to the other, false otherwise
 	/// \details The operator tests for equality using <tt>this.m_modulus == rhs.m_modulus</tt>.
 	bool operator==(const ModularArithmetic &rhs) const
 		{return m_modulus == rhs.m_modulus;}
 
-	static const RandomizationParameter DefaultRandomizationParameter ;
+	static const RandomizationParameter DefaultRandomizationParameter;
+
+private:
+	// TODO: Clang on OS X needs a real operator=.
+	// Squash warning on missing assignment operator.
+	// ModularArithmetic& operator=(const ModularArithmetic &ma);
 
 protected:
 	Integer m_modulus;
@@ -282,7 +303,7 @@ public:
 	MontgomeryRepresentation(const Integer &modulus);
 
 	/// \brief Clone a MontgomeryRepresentation
-	/// \returns pointer to a new MontgomeryRepresentation
+	/// \return pointer to a new MontgomeryRepresentation
 	/// \details Clone effectively copy constructs a new MontgomeryRepresentation. The caller is
 	///   responsible for deleting the pointer returned from this method.
 	virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);}

+ 133 - 17
include/cryptlib/modes.h

@@ -50,17 +50,58 @@ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher
 {
 public:
 	virtual ~CipherModeBase() {}
+
+	// Algorithm class
+	std::string AlgorithmProvider() const {
+		return m_cipher != NULLPTR ? m_cipher->AlgorithmProvider() : "C++";
+	}
+
+	/// \brief Returns smallest valid key length
+	/// \return the minimum key length, in bytes
 	size_t MinKeyLength() const {return m_cipher->MinKeyLength();}
+
+	/// \brief Returns largest valid key length
+	/// \return the maximum key length, in bytes
 	size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();}
+
+	/// \brief Returns default key length
+	/// \return the default key length, in bytes
 	size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
-	size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);}
-	bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);}
 
+	/// \brief Returns a valid key length for the algorithm
+	/// \param keylength the size of the key, in bytes
+	/// \return the valid key length, in bytes
+	/// \details keylength is provided in bytes, not bits. If keylength is less than MIN_KEYLENGTH,
+	///   then the function returns MIN_KEYLENGTH. If keylength is greater than MAX_KEYLENGTH,
+	///   then the function returns MAX_KEYLENGTH. if If keylength is a multiple of KEYLENGTH_MULTIPLE,
+	///   then keylength is returned. Otherwise, the function returns a \a lower multiple of
+	///   KEYLENGTH_MULTIPLE.
+	size_t GetValidKeyLength(size_t keylength) const {return m_cipher->GetValidKeyLength(keylength);}
+
+	/// \brief Returns whether keylength is a valid key length
+	/// \param keylength the requested keylength
+	/// \return true if keylength is valid, false otherwise
+	/// \details Internally the function calls GetValidKeyLength()
+	bool IsValidKeyLength(size_t keylength) const {return m_cipher->IsValidKeyLength(keylength);}
+
+	/// \brief Provides input and output data alignment for optimal performance.
+	/// \return the input data alignment that provides optimal performance
+	/// \sa GetAlignment() and OptimalBlockSize()
 	unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();}
 
+	/// \brief Returns length of the IV accepted by this object
+	/// \return the size of an IV, in bytes
+	/// \throw NotImplemented() if the object does not support resynchronization
+	/// \details The default implementation throws NotImplemented
 	unsigned int IVSize() const {return BlockSize();}
+
+	/// \brief Minimal requirement for secure IVs
+	/// \return the secure IV requirement of the algorithm
 	virtual IV_Requirement IVRequirement() const =0;
 
+	/// \brief Set external block cipher
+	/// \param cipher An external block cipher
+	/// \details The cipher should be keyed.
 	void SetCipher(BlockCipher &cipher)
 	{
 		this->ThrowIfResynchronizable();
@@ -68,6 +109,11 @@ public:
 		this->ResizeBuffers();
 	}
 
+	/// \brief Set external block cipher and IV
+	/// \param cipher An external block cipher
+	/// \param iv a byte array used to resynchronize the cipher
+	/// \param feedbackSize the feedback size, in bytes
+	/// \details The cipher should be keyed.
 	void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
 	{
 		this->ThrowIfInvalidIV(iv);
@@ -80,7 +126,11 @@ public:
 
 protected:
 	CipherModeBase() : m_cipher(NULLPTR) {}
-	inline unsigned int BlockSize() const {CRYPTOPP_ASSERT(m_register.size() > 0); return (unsigned int)m_register.size();}
+	inline unsigned int BlockSize() const
+	{
+		CRYPTOPP_ASSERT(m_register.size() > 0);
+		return static_cast<unsigned int>(m_register.size());
+	}
 	virtual void SetFeedbackSize(unsigned int feedbackSize)
 	{
 		if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
@@ -90,7 +140,7 @@ protected:
 	virtual void ResizeBuffers();
 
 	BlockCipher *m_cipher;
-	AlignedSecByteBlock m_register;
+	SecByteBlock m_register;
 };
 
 /// \brief Block cipher mode of operation common operations
@@ -118,31 +168,40 @@ public:
 	CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "CFB";}
 
 	virtual ~CFB_ModePolicy() {}
+	CFB_ModePolicy() : m_feedbackSize(0) {}
 	IV_Requirement IVRequirement() const {return RANDOM_IV;}
 
 protected:
 	unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
-	byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
 	bool CanIterate() const {return m_feedbackSize == BlockSize();}
 	void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount);
 	void TransformRegister();
 	void CipherResynchronize(const byte *iv, size_t length);
 	void SetFeedbackSize(unsigned int feedbackSize);
 	void ResizeBuffers();
+	byte * GetRegisterBegin();
 
 	SecByteBlock m_temp;
 	unsigned int m_feedbackSize;
 };
 
-inline void CopyOrZero(void *dest, size_t d, const void *src, size_t s)
+/// \brief Initialize a block of memory
+/// \param dest the destination block of memory
+/// \param dsize the size of the destination block, in bytes
+/// \param src the source block of memory
+/// \param ssize the size of the source block, in bytes
+/// \details CopyOrZero copies ssize bytes from source to destination if
+///   src is not NULL. If src is NULL then dest is zero'd. Bounds are not
+///   checked at runtime. Debug builds assert if ssize exceeds dsize.
+inline void CopyOrZero(void *dest, size_t dsize, const void *src, size_t ssize)
 {
 	CRYPTOPP_ASSERT(dest);
-	CRYPTOPP_ASSERT(d >= s);
+	CRYPTOPP_ASSERT(dsize >= ssize);
 
-	if (src)
-		memcpy_s(dest, d, src, s);
+	if (src != NULLPTR)
+		memcpy_s(dest, dsize, src, ssize);
 	else
-		memset(dest, 0, d);
+		std::memset(dest, 0, dsize);
 }
 
 /// \brief OFB block cipher mode of operation
@@ -154,7 +213,7 @@ public:
 	bool CipherIsRandomAccess() const {return false;}
 	IV_Requirement IVRequirement() const {return UNIQUE_IV;}
 
-private:
+protected:
 	unsigned int GetBytesPerIteration() const {return BlockSize();}
 	unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
 	void WriteKeystream(byte *keystreamBuffer, size_t iterationCount);
@@ -183,7 +242,8 @@ protected:
 	void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
 	void SeekToIteration(lword iterationCount);
 
-	AlignedSecByteBlock m_counterArray;
+	// adv_simd.h increments the counter
+	mutable SecByteBlock m_counterArray;
 };
 
 /// \brief Block cipher mode of operation default implementation
@@ -195,8 +255,10 @@ public:
 	unsigned int MandatoryBlockSize() const {return BlockSize();}
 	bool IsRandomAccess() const {return false;}
 	bool IsSelfInverting() const {return false;}
-	bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
-	void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
+	bool IsForwardTransformation() const
+		{return m_cipher->IsForwardTransformation();}
+	void Resynchronize(const byte *iv, int length=-1)
+		{memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
 
 protected:
 	bool RequireAlignedInput() const {return true;}
@@ -214,7 +276,7 @@ public:
 	void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs)
 		{m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();}
 	IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
-	unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
+	unsigned int OptimalBlockSize() const {return static_cast<unsigned int>(BlockSize() * m_cipher->OptimalNumberOfParallelBlocks());}
 	void ProcessData(byte *outString, const byte *inString, size_t length);
 };
 
@@ -251,7 +313,7 @@ protected:
 	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
 	{
 		CBC_Encryption::UncheckedSetKey(key, length, params);
-		m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULLPTR);
+		m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), static_cast<byte *>(NULLPTR));
 	}
 
 	byte *m_stolenIV;
@@ -267,7 +329,7 @@ public:
 protected:
 	virtual void ResizeBuffers();
 
-	AlignedSecByteBlock m_temp;
+	SecByteBlock m_temp;
 };
 
 /// \brief CBC-CTS block cipher mode of operation decryption operation
@@ -284,29 +346,61 @@ template <class CIPHER, class BASE>
 class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> >
 {
 public:
+	/// \brief Provides the name of this algorithm
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like \a AES or \a AES/GCM. Some algorithms
+	///   do not have standard names yet. For example, there is no standard algorithm name for
+	///   Shoup's ECIES.
 	static std::string CRYPTOPP_API StaticAlgorithmName()
 		{return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();}
 
+	/// \brief Construct a CipherModeFinalTemplate
 	CipherModeFinalTemplate_CipherHolder()
 	{
 		this->m_cipher = &this->m_object;
 		this->ResizeBuffers();
 	}
+
+	/// \brief Construct a CipherModeFinalTemplate
+	/// \param key a byte array used to key the cipher
+	/// \param length size of the key in bytes
+	/// \details key must be at least DEFAULT_KEYLENGTH in length. Internally, the function calls
+	///    SimpleKeyingInterface::SetKey.
 	CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length)
 	{
 		this->m_cipher = &this->m_object;
 		this->SetKey(key, length);
 	}
+
+	/// \brief Construct a CipherModeFinalTemplate
+	/// \param key a byte array used to key the cipher
+	/// \param length size of the key in bytes
+	/// \param iv a byte array used to resynchronize the cipher
+	/// \details key must be at least DEFAULT_KEYLENGTH in length. iv must be IVSize() or
+	///    BLOCKSIZE in length. Internally, the function calls SimpleKeyingInterface::SetKey.
 	CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv)
 	{
 		this->m_cipher = &this->m_object;
 		this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize())));
 	}
+
+	/// \brief Construct a CipherModeFinalTemplate
+	/// \param key a byte array used to key the cipher
+	/// \param length size of the key in bytes
+	/// \param iv a byte array used to resynchronize the cipher
+	/// \param feedbackSize the feedback size, in bytes
+	/// \details key must be at least DEFAULT_KEYLENGTH in length. iv must be IVSize() or
+	///    BLOCKSIZE in length. Internally, the function calls SimpleKeyingInterface::SetKey.
 	CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize)
 	{
 		this->m_cipher = &this->m_object;
 		this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize));
 	}
+
+	// Algorithm class
+	std::string AlgorithmProvider() const {
+		return this->m_cipher->AlgorithmProvider();
+	}
 };
 
 /// \tparam BASE CipherModeFinalTemplate_CipherHolder base class
@@ -315,14 +409,36 @@ template <class BASE>
 class CipherModeFinalTemplate_ExternalCipher : public BASE
 {
 public:
+	/// \brief Construct a default CipherModeFinalTemplate
+	/// \details The cipher is not keyed.
 	CipherModeFinalTemplate_ExternalCipher() {}
+
+	/// \brief Construct a CipherModeFinalTemplate
+	/// \param cipher An external block cipher
+	/// \details The cipher should be keyed.
 	CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
 		{this->SetCipher(cipher);}
+
+	/// \brief Construct a CipherModeFinalTemplate
+	/// \param cipher An external block cipher
+	/// \param iv a byte array used to resynchronize the cipher
+	/// \param feedbackSize the feedback size, in bytes
+	/// \details The cipher should be keyed.
 	CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
 		{this->SetCipherWithIV(cipher, iv, feedbackSize);}
 
+	/// \brief Provides the name of this algorithm
+	/// \return the standard algorithm name
+	/// \details The standard algorithm name can be a name like \a AES or \a AES/GCM. Some algorithms
+	///   do not have standard names yet. For example, there is no standard algorithm name for
+	///   Shoup's ECIES.
+	/// \note  AlgorithmName is not universally implemented yet
 	std::string AlgorithmName() const
 		{return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();}
+
+	// Algorithm class
+	std::string AlgorithmProvider() const
+		{return this->m_cipher->AlgorithmProvider();}
 };
 
 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;

+ 47 - 7
include/cryptlib/mqueue.h

@@ -1,3 +1,8 @@
+// mqueue.h - originally written and placed in the public domain by Wei Dai
+
+/// \file
+/// \brief Classes for an unlimited queue to store messages
+
 #ifndef CRYPTOPP_MQUEUE_H
 #define CRYPTOPP_MQUEUE_H
 
@@ -10,12 +15,21 @@
 
 NAMESPACE_BEGIN(CryptoPP)
 
-/// Message Queue
+/// \brief Data structure used to store messages
+/// \details The queue is implemented with a ByteQueue.
+/// \sa <A HREF="https://www.cryptopp.com/wiki/MessageQueue">MessageQueue</A>
+///  on the Crypto++ wiki.
+/// \since Crypto++ 2.0
 class CRYPTOPP_DLL MessageQueue : public AutoSignaling<BufferedTransformation>
 {
 public:
+	virtual ~MessageQueue() {}
+
+	/// \brief Construct a MessageQueue
+	/// \param nodeSize the initial node size
 	MessageQueue(unsigned int nodeSize=256);
 
+	// BufferedTransformation
 	void IsolatedInitialize(const NameValuePairs &parameters)
 		{m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);}
 	size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
@@ -54,10 +68,23 @@ public:
 	unsigned int NumberOfMessageSeries() const
 		{return (unsigned int)m_messageCounts.size()-1;}
 
+	/// \brief Copy messages from this object to another BufferedTransformation.
+	/// \param target the destination BufferedTransformation
+	/// \param count the number of messages to copy
+	/// \param channel the channel on which the transfer should occur
+	/// \return the number of messages that remain in the copy (i.e., messages not copied)
 	unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
 
+	/// \brief Peek data in the queue
+	/// \param contiguousSize the size of the data
+	/// \details Spy() peeks at data at the head of the queue. Spy() does
+	///  not remove data from the queue.
+	/// \details The data's size is returned in <tt>contiguousSize</tt>.
+	///  Spy() returns the size of the first message in the list.
 	const byte * Spy(size_t &contiguousSize) const;
 
+	/// \brief Swap contents with another MessageQueue
+	/// \param rhs the other MessageQueue
 	void swap(MessageQueue &rhs);
 
 private:
@@ -66,26 +93,39 @@ private:
 	std::deque<unsigned int> m_messageCounts;
 };
 
-
-/// A filter that checks messages on two channels for equality
+/// \brief Filter that checks messages on two channels for equality
 class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable<Multichannel<Filter> >
 {
 public:
-	struct MismatchDetected : public Exception {MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}};
-
-	/*! if throwIfNotEqual is false, this filter will output a '\\0' byte when it detects a mismatch, '\\1' otherwise */
+	/// \brief Different messages were detected
+	struct MismatchDetected : public Exception
+	{
+		/// \brief Construct a MismatchDetected exception
+		MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}
+	};
+
+	/// \brief Construct an EqualityComparisonFilter
+	/// \param attachment an attached transformation
+	/// \param throwIfNotEqual flag indicating whether the objects throws
+	/// \param firstChannel string naming the first channel
+	/// \param secondChannel string naming the second channel
+	/// \throw MismatchDetected if throwIfNotEqual is true and not equal
+	/// \details If throwIfNotEqual is false, this filter will output a '\\0'
+	///  byte when it detects a mismatch, '\\1' otherwise.
 	EqualityComparisonFilter(BufferedTransformation *attachment=NULLPTR, bool throwIfNotEqual=true, const std::string &firstChannel="0", const std::string &secondChannel="1")
 		: m_throwIfNotEqual(throwIfNotEqual), m_mismatchDetected(false)
 		, m_firstChannel(firstChannel), m_secondChannel(secondChannel)
 		{Detach(attachment);}
 
+	// BufferedTransformation
 	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
 	bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
 
-private:
+protected:
 	unsigned int MapChannel(const std::string &channel) const;
 	bool HandleMismatchDetected(bool blocking);
 
+private:
 	bool m_throwIfNotEqual, m_mismatchDetected;
 	std::string m_firstChannel, m_secondChannel;
 	MessageQueue m_q[2];

+ 56 - 11
include/cryptlib/mqv.h

@@ -94,10 +94,11 @@ public:
 	CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
 
 	/// \brief Provides the size of the agreed value
-	/// \return size of agreed value produced  in this domain
-	/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>, which means the
-	///   element is encoded in a non-reversible format. A non-reversible format means its a raw byte array,
-	///   and it lacks presentation format like an ASN.1 BIT_STRING or OCTET_STRING.
+	/// \return size of agreed value produced in this domain
+	/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
+	///  which means the element is encoded in a non-reversible format. A
+	///  non-reversible format means its a raw byte array, and it lacks presentation
+	///  format like an ASN.1 BIT_STRING or OCTET_STRING.
 	unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
 
 	/// \brief Provides the size of the static private key
@@ -107,15 +108,17 @@ public:
 
 	/// \brief Provides the size of the static public key
 	/// \return size of static public keys in this domain
-	/// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>, which means the
-	///   element is encoded in a reversible format. A reversible format means it has a presentation format,
-	///   and its an ANS.1 encoded element or point.
+	/// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>,
+	///  which means the element is encoded in a reversible format. A reversible
+	///  format means it has a presentation format, and its an ANS.1 encoded element
+	///  or point.
 	unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
 
 	/// \brief Generate static private key in this domain
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param privateKey a byte buffer for the generated private key in this domain
-	/// \details The private key is a random scalar used as an exponent in the range <tt>[1,MaxExponent()]</tt>.
+	/// \details The private key is a random scalar used as an exponent in the range
+	///  <tt>[1,MaxExponent()]</tt>.
 	/// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
 	void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
 	{
@@ -127,8 +130,9 @@ public:
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param privateKey a byte buffer with the previously generated private key
 	/// \param publicKey a byte buffer for the generated public key in this domain
-	/// \details The public key is an element or point on the curve, and its stored in a revrsible format.
-	///    A reversible format means it has a presentation format, and its an ANS.1 encoded element or point.
+	/// \details The public key is an element or point on the curve, and its stored
+	///  in a revrsible format. A reversible format means it has a presentation
+	///  format, and its an ANS.1 encoded element or point.
 	/// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
 	void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
 	{
@@ -139,9 +143,22 @@ public:
 		params.EncodeElement(true, y, publicKey);
 	}
 
+	/// \brief Provides the size of the ephemeral private key
+	/// \return size of ephemeral private keys in this domain
+	/// \details An ephemeral private key is a private key and public key.
+	///  The serialized size is different than a static private key.
 	unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
+
+	/// \brief Provides the size of the ephemeral public key
+	/// \return size of ephemeral public keys in this domain
+	/// \details An ephemeral public key is a public key.
+	///  The serialized size is the same as a static public key.
 	unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
 
+	/// \brief Generate ephemeral private key in this domain
+	/// \param rng a RandomNumberGenerator derived class
+	/// \param privateKey a byte buffer for the generated private key in this domain
+	/// \pre <tt>COUNTOF(privateKey) == EphemeralPrivateKeyLength()</tt>
 	void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
 	{
 		const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
@@ -151,12 +168,40 @@ public:
 		params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
 	}
 
+	/// \brief Generate ephemeral public key from a private key in this domain
+	/// \param rng a RandomNumberGenerator derived class
+	/// \param privateKey a byte buffer with the previously generated private key
+	/// \param publicKey a byte buffer for the generated public key in this domain
+	/// \pre <tt>COUNTOF(publicKey) == EphemeralPublicKeyLength()</tt>
 	void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
 	{
 		CRYPTOPP_UNUSED(rng);
-		memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
+		std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
 	}
 
+	/// \brief Derive agreed value or shared secret
+	/// \param agreedValue the shared secret
+	/// \param staticPrivateKey your long term private key
+	/// \param ephemeralPrivateKey your ephemeral private key
+	/// \param staticOtherPublicKey couterparty's long term public key
+	/// \param ephemeralOtherPublicKey couterparty's ephemeral public key
+	/// \param validateStaticOtherPublicKey flag indicating validation
+	/// \return true upon success, false in case of failure
+	/// \details Agree() performs the authenticated key agreement. Agree()
+	///  derives a shared secret from your private keys and couterparty's
+	///  public keys. Each instance or run of the protocol should use a new
+	///  ephemeral key pair.
+	/// \details The other's ephemeral public key will always be validated at
+	///  Level 1 to ensure it is a point on the curve.
+	///  <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
+	///  static public key is validated. If you have previously validated the
+	///  couterparty's static public key, then use
+	///  <tt>validateStaticOtherPublicKey=false</tt> to save time.
+	/// \pre <tt>COUNTOF(agreedValue) == AgreedValueLength()</tt>
+	/// \pre <tt>COUNTOF(staticPrivateKey) == StaticPrivateKeyLength()</tt>
+	/// \pre <tt>COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength()</tt>
+	/// \pre <tt>COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength()</tt>
+	/// \pre <tt>COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength()</tt>
 	bool Agree(byte *agreedValue,
 		const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
 		const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,

+ 99 - 78
include/cryptlib/naclite.h

@@ -3,40 +3,48 @@
 //          Daniel J. Bernstein, Bernard van Gastel, Wesley Janssen,
 //          Tanja Lange, Peter Schwabe and Sjaak Smetsers.
 
+// The Tweet API was added to the Crypto++ library to cross-validate results.
+// We debated over putting it in the Test namespace, but settled for the NaCl
+// namespace to segregate it from other parts of the library.
+
 /// \file naclite.h
 /// \brief Crypto++ interface to TweetNaCl library (20140917)
-/// \details TweetNaCl is a compact reimplementation of the NaCl library by
-///   Daniel J. Bernstein, Bernard van Gastel, Wesley Janssen, Tanja Lange,
-///   Peter Schwabe and Sjaak Smetsers. The library is less than 20 KB in size
-///   and provides 25 of the NaCl library functions.
+/// \details TweetNaCl is a compact reimplementation of the NaCl library
+///   by Daniel J. Bernstein, Bernard van Gastel, Wesley Janssen, Tanja
+///   Lange, Peter Schwabe and Sjaak Smetsers. The library is less than
+///   20 KB in size and provides 25 of the NaCl library functions.
 /// \details The compact library uses curve25519, XSalsa20, Poly1305 and
-///   SHA-512 as default primitives, and includes both x25519 key exchange and
-///   ed25519 signatures. The complete list of functions can be found in
-///   <A HREF="https://tweetnacl.cr.yp.to/tweetnacl-20140917.pdf">TweetNaCl:
+///   SHA-512 as default primitives, and includes both x25519 key exchange
+///   and ed25519 signatures. The complete list of functions can be found
+///   in <A
+///   HREF="https://tweetnacl.cr.yp.to/tweetnacl-20140917.pdf">TweetNaCl:
 ///   A crypto library in 100 tweets</A> (20140917), Table 1, page 5.
-/// \details Crypto++ rejects small order elements using libsodium's blacklist. The
-///   TweetNaCl library allowed them but the library predated the attack. If you wish
-///   to allow small elements then use the "unchecked" versions of crypto_box_unchecked,
-///   crypto_box_open_unchecked and crypto_box_beforenm_unchecked.
-/// \details TweetNaCl is well written but not well optimzed. It runs 2x to 3x
-///   slower than optimized routines from libsodium. However, the library is still
-///    2x to 4x faster than the algorithms NaCl was designed to replace.
+/// \details Crypto++ rejects small order elements using libsodium's
+///   blacklist. The TweetNaCl library allowed them but the library predated
+///   the attack. If you wish to allow small elements then use the "unchecked"
+///   versions of crypto_box_unchecked, crypto_box_open_unchecked and
+///   crypto_box_beforenm_unchecked.
+/// \details TweetNaCl is well written but not well optimzed. It runs about
+///   10x slower than optimized routines from libsodium. However, the library
+///   is still 2x to 4x faster than the algorithms NaCl was designed to replace
+///   and allows cross-checking results from an independent implementation.
 /// \details The Crypto++ wrapper for TweetNaCl requires OS features. That is,
-///    <tt>NO_OS_DEPENDENCE</tt> cannot be defined. It is due to TweetNaCl's
-///    internal function <tt>randombytes</tt>. Crypto++ used
-///    <tt>DefaultAutoSeededRNG</tt> within <tt>randombytes</tt>, so OS integration
-///    must be enabled. You can use another generator like <tt>RDRAND</tt> to
-///    avoid the restriction.
-/// \sa <A HREF="https://cr.yp.to/highspeed/coolnacl-20120725.pdf">The security impact
-///   of a new cryptographic library</A>, <A
+///   <tt>NO_OS_DEPENDENCE</tt> cannot be defined. It is due to TweetNaCl's
+///   internal function <tt>randombytes</tt>. Crypto++ used
+///   <tt>DefaultAutoSeededRNG</tt> within <tt>randombytes</tt>, so OS
+///   integration must be enabled. You can use another generator like
+///   <tt>RDRAND</tt> to avoid the restriction.
+/// \sa <A HREF="https://cr.yp.to/highspeed/coolnacl-20120725.pdf">The security
+///   impact of a new cryptographic library</A>, <A
 ///   HREF="https://tweetnacl.cr.yp.to/tweetnacl-20140917.pdf">TweetNaCl:
 ///   A crypto library in 100 tweets</A> (20140917), <A
-///   HREF="https://eprint.iacr.org/2017/806.pdf">May the Fourth Be With You: A
-///   Microarchitectural Side Channel Attack on Several Real-World Applications of
-///   Curve25519</A>, <A
+///   HREF="https://eprint.iacr.org/2017/806.pdf">May the Fourth Be With You:
+///   A Microarchitectural Side Channel Attack on Several Real-World
+///   Applications of Curve25519</A>, <A
 ///   HREF="https://github.com/jedisct1/libsodium/commit/afabd7e7386e1194">libsodium
-///   commit afabd7e7386e1194</A> and <A HREF="https://tools.ietf.org/html/rfc7748">RFC
-///   7748, Elliptic Curves for Security</A>, Section 6.
+///   commit afabd7e7386e1194</A> and <A
+///   HREF="https://tools.ietf.org/html/rfc7748">RFC 7748, Elliptic Curves for
+///   Security</A>, Section 6.
 /// \since Crypto++ 6.0
 
 #ifndef CRYPTOPP_NACL_H
@@ -45,7 +53,7 @@
 #include "config.h"
 #include "stdcpp.h"
 
-#if defined(NO_OS_DEPENDENCE)
+#if defined(NO_OS_DEPENDENCE) || !defined(OS_RNG_AVAILABLE)
 # define CRYPTOPP_DISABLE_NACL 1
 #endif
 
@@ -56,85 +64,85 @@ NAMESPACE_BEGIN(NaCl)
 
 /// \brief Hash size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/hash.html">NaCl crypto_hash documentation</A>
-CRYPTOPP_CONSTANT(crypto_hash_BYTES = 64)
+CRYPTOPP_CONSTANT(crypto_hash_BYTES = 64);
 
 /// \brief Key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/stream.html">NaCl crypto_stream documentation</A>
-CRYPTOPP_CONSTANT(crypto_stream_KEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_stream_KEYBYTES = 32);
 /// \brief Nonce size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/stream.html">NaCl crypto_stream documentation</A>
-CRYPTOPP_CONSTANT(crypto_stream_NONCEBYTES = 24)
+CRYPTOPP_CONSTANT(crypto_stream_NONCEBYTES = 24);
 
 /// \brief Key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/auth.html">NaCl crypto_auth documentation</A>
-CRYPTOPP_CONSTANT(crypto_auth_KEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_auth_KEYBYTES = 32);
 /// \brief Tag size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/auth.html">NaCl crypto_auth documentation</A>
-CRYPTOPP_CONSTANT(crypto_auth_BYTES = 16)
+CRYPTOPP_CONSTANT(crypto_auth_BYTES = 16);
 
 /// \brief Key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/onetimeauth.html">NaCl crypto_onetimeauth documentation</A>
-CRYPTOPP_CONSTANT(crypto_onetimeauth_KEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_onetimeauth_KEYBYTES = 32);
 /// \brief Tag size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/onetimeauth.html">NaCl crypto_onetimeauth documentation</A>
-CRYPTOPP_CONSTANT(crypto_onetimeauth_BYTES = 16)
+CRYPTOPP_CONSTANT(crypto_onetimeauth_BYTES = 16);
 
 /// \brief Key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/secretbox.html">NaCl crypto_secretbox documentation</A>
-CRYPTOPP_CONSTANT(crypto_secretbox_KEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_secretbox_KEYBYTES = 32);
 /// \brief Nonce size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/secretbox.html">NaCl crypto_secretbox documentation</A>
-CRYPTOPP_CONSTANT(crypto_secretbox_NONCEBYTES = 24)
+CRYPTOPP_CONSTANT(crypto_secretbox_NONCEBYTES = 24);
 /// \brief Zero-padded message prefix in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/secretbox.html">NaCl crypto_secretbox documentation</A>
-CRYPTOPP_CONSTANT(crypto_secretbox_ZEROBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_secretbox_ZEROBYTES = 32);
 /// \brief Zero-padded message prefix in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/secretbox.html">NaCl crypto_secretbox documentation</A>
-CRYPTOPP_CONSTANT(crypto_secretbox_BOXZEROBYTES = 16)
+CRYPTOPP_CONSTANT(crypto_secretbox_BOXZEROBYTES = 16);
 
 /// \brief Private key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_SECRETKEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_box_SECRETKEYBYTES = 32);
 /// \brief Public key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_PUBLICKEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_box_PUBLICKEYBYTES = 32);
 /// \brief Nonce size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_NONCEBYTES = 24)
+CRYPTOPP_CONSTANT(crypto_box_NONCEBYTES = 24);
 /// \brief Message 0-byte prefix in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_ZEROBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_box_ZEROBYTES = 32);
 /// \brief Open box 0-byte prefix in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_BOXZEROBYTES = 16)
+CRYPTOPP_CONSTANT(crypto_box_BOXZEROBYTES = 16);
 /// \brief Precomputation 0-byte prefix in bytes in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_BEFORENMBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_box_BEFORENMBYTES = 32);
 /// \brief MAC size in bytes
 /// \details crypto_box_MACBYTES was missing from tweetnacl.h. Its is defined as
 ///   crypto_box_curve25519xsalsa20poly1305_MACBYTES, which is defined as 16U.
 /// \sa <A HREF="https://nacl.cr.yp.to/hash.html">NaCl crypto_box documentation</A>
-CRYPTOPP_CONSTANT(crypto_box_MACBYTES = 16)
+CRYPTOPP_CONSTANT(crypto_box_MACBYTES = 16);
 
 /// \brief Private key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
-CRYPTOPP_CONSTANT(crypto_sign_SECRETKEYBYTES = 64)
+CRYPTOPP_CONSTANT(crypto_sign_SECRETKEYBYTES = 64);
 /// \brief Public key size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
-CRYPTOPP_CONSTANT(crypto_sign_PUBLICKEYBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_sign_PUBLICKEYBYTES = 32);
 /// \brief Seed size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
-CRYPTOPP_CONSTANT(crypto_sign_SEEDBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_sign_SEEDBYTES = 32);
 /// \brief Signature size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
-CRYPTOPP_CONSTANT(crypto_sign_BYTES = 64)
+CRYPTOPP_CONSTANT(crypto_sign_BYTES = 64);
 
 /// \brief Group element size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/scalarmult.html">NaCl crypto_scalarmult documentation</A>
-CRYPTOPP_CONSTANT(crypto_scalarmult_BYTES = 32)
+CRYPTOPP_CONSTANT(crypto_scalarmult_BYTES = 32);
 /// \brief Integer size in bytes
 /// \sa <A HREF="https://nacl.cr.yp.to/scalarmult.html">NaCl crypto_scalarmult documentation</A>
-CRYPTOPP_CONSTANT(crypto_scalarmult_SCALARBYTES = 32)
+CRYPTOPP_CONSTANT(crypto_scalarmult_SCALARBYTES = 32);
 
 /// \brief Encrypt and authenticate a message
 /// \param c output byte buffer
@@ -144,7 +152,7 @@ CRYPTOPP_CONSTANT(crypto_scalarmult_SCALARBYTES = 32)
 /// \param y other's public key
 /// \param x private key
 /// \details crypto_box() uses crypto_box_curve25519xsalsa20poly1305
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
 /// \since Crypto++ 6.0
 int crypto_box(byte *c,const byte *m,word64 d,const byte *n,const byte *y,const byte *x);
@@ -157,7 +165,7 @@ int crypto_box(byte *c,const byte *m,word64 d,const byte *n,const byte *y,const
 /// \param y other's public key
 /// \param x private key
 /// \details crypto_box_open() uses crypto_box_curve25519xsalsa20poly1305
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
 /// \since Crypto++ 6.0
 int crypto_box_open(byte *m,const byte *c,word64 d,const byte *n,const byte *y,const byte *x);
@@ -165,7 +173,7 @@ int crypto_box_open(byte *m,const byte *c,word64 d,const byte *n,const byte *y,c
 /// \brief Generate a keypair for encryption
 /// \param y public key byte buffer
 /// \param x private key byte buffer
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
 /// \since Crypto++ 6.0
 int crypto_box_keypair(byte *y,byte *x);
@@ -176,7 +184,7 @@ int crypto_box_keypair(byte *y,byte *x);
 /// \param x private key
 /// \details crypto_box_beforenm() performs message-independent precomputation to derive the key.
 ///   Once the key is derived multiple calls to crypto_box_afternm() can be made to process the message.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
 /// \since Crypto++ 6.0
 int crypto_box_beforenm(byte *k,const byte *y,const byte *x);
@@ -190,7 +198,7 @@ int crypto_box_beforenm(byte *k,const byte *y,const byte *x);
 /// \details crypto_box_afternm() performs message-dependent computation using the derived the key.
 ///   Once the key is derived using crypto_box_beforenm() multiple calls to crypto_box_afternm()
 ///   can be made to process the message.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
 /// \since Crypto++ 6.0
 int crypto_box_afternm(byte *c,const byte *m,word64 d,const byte *n,const byte *k);
@@ -204,7 +212,7 @@ int crypto_box_afternm(byte *c,const byte *m,word64 d,const byte *n,const byte *
 /// \details crypto_box_afternm() performs message-dependent computation using the derived the key.
 ///   Once the key is derived using crypto_box_beforenm() multiple calls to crypto_box_open_afternm()
 ///   can be made to process the message.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>
 /// \since Crypto++ 6.0
 int crypto_box_open_afternm(byte *m,const byte *c,word64 d,const byte *n,const byte *k);
@@ -222,7 +230,7 @@ int crypto_box_open_afternm(byte *m,const byte *c,word64 d,const byte *n,const b
 ///   interop with early versions of NaCl, libsodium and other libraries does not exist. The
 ///   downlevel interop may also be needed of cryptocurrencies like Bitcoin, Ethereum, Monero
 ///   and Zcash.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \warning This version of crypto_box() does not check for small order elements. It should not
 ///   be used in new software.
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>,
@@ -246,7 +254,7 @@ int crypto_box_unchecked(byte *c,const byte *m,word64 d,const byte *n,const byte
 ///   interop with early versions of NaCl, libsodium and other libraries does not exist. The
 ///   downlevel interop may also be needed of cryptocurrencies like Bitcoin, Ethereum, Monero
 ///   and Zcash.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \warning This version of crypto_box_open() does not check for small order elements. It should not
 ///   be used in new software.
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>,
@@ -268,7 +276,7 @@ int crypto_box_open_unchecked(byte *m,const byte *c,word64 d,const byte *n,const
 ///   interop with early versions of NaCl, libsodium and other libraries does not exist. The
 ///   downlevel interop may also be needed of cryptocurrencies like Bitcoin, Ethereum, Monero
 ///   and Zcash.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \warning This version of crypto_box_beforenm() does not check for small order elements. It should not
 ///   be used in new software.
 /// \sa <A HREF="https://nacl.cr.yp.to/box.html">NaCl crypto_box documentation</A>,
@@ -283,60 +291,60 @@ int crypto_box_beforenm_unchecked(byte *k,const byte *y,const byte *x);
 int crypto_core_salsa20(byte *out,const byte *in,const byte *k,const byte *c);
 
 /// \brief TODO
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \since Crypto++ 6.0
 int crypto_core_hsalsa20(byte *out,const byte *in,const byte *k,const byte *c);
 
 /// \brief Hash multiple blocks
 /// \details crypto_hashblocks() uses crypto_hashblocks_sha512.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/hash.html">NaCl crypto_hash documentation</A>
 /// \since Crypto++ 6.0
 int crypto_hashblocks(byte *x,const byte *m,word64 n);
 
 /// \brief Hash a message
 /// \details crypto_hash() uses crypto_hash_sha512.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/hash.html">NaCl crypto_hash documentation</A>
 /// \since Crypto++ 6.0
 int crypto_hash(byte *out,const byte *m,word64 n);
 
 /// \brief Create an authentication tag for a message
 /// \details crypto_onetimeauth() uses crypto_onetimeauth_poly1305.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/onetimeauth.html">NaCl crypto_onetimeauth documentation</A>
 /// \since Crypto++ 6.0
 int crypto_onetimeauth(byte *out,const byte *m,word64 n,const byte *k);
 
 /// \brief Verify an authentication tag on a message
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/onetimeauth.html">NaCl crypto_onetimeauth documentation</A>
 /// \since Crypto++ 6.0
 int crypto_onetimeauth_verify(const byte *h,const byte *m,word64 n,const byte *k);
 
 /// \brief Scalar multiplication of a point
 /// \details crypto_scalarmult() uses crypto_scalarmult_curve25519
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/scalarmult.html">NaCl crypto_scalarmult documentation</A>
 /// \since Crypto++ 6.0
 int crypto_scalarmult(byte *q,const byte *n,const byte *p);
 
 /// \brief Scalar multiplication of base point
 /// \details crypto_scalarmult_base() uses crypto_scalarmult_curve25519
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/scalarmult.html">NaCl crypto_scalarmult documentation</A>
 /// \since Crypto++ 6.0
 int crypto_scalarmult_base(byte *q,const byte *n);
 
 /// \brief Encrypt and authenticate a message
 /// \details crypto_secretbox() uses a symmetric key to encrypt and authenticate a message.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/secretbox.html">NaCl crypto_secretbox documentation</A>
 /// \since Crypto++ 6.0
 int crypto_secretbox(byte *c,const byte *m,word64 d,const byte *n,const byte *k);
 
 /// \brief Verify and decrypt a message
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/secretbox.html">NaCl crypto_secretbox documentation</A>
 /// \since Crypto++ 6.0
 int crypto_secretbox_open(byte *m,const byte *c,word64 d,const byte *n,const byte *k);
@@ -348,7 +356,7 @@ int crypto_secretbox_open(byte *m,const byte *c,word64 d,const byte *n,const byt
 /// \param n size of the input byte buffer
 /// \param sk private key
 /// \details crypto_sign() uses crypto_sign_ed25519.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
 /// \since Crypto++ 6.0
 int crypto_sign(byte *sm,word64 *smlen,const byte *m,word64 n,const byte *sk);
@@ -359,7 +367,7 @@ int crypto_sign(byte *sm,word64 *smlen,const byte *m,word64 n,const byte *sk);
 /// \param sm input byte buffer
 /// \param n size of the input byte buffer
 /// \param pk public key
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
 /// \since Crypto++ 6.0
 int crypto_sign_open(byte *m,word64 *mlen,const byte *sm,word64 n,const byte *pk);
@@ -368,44 +376,57 @@ int crypto_sign_open(byte *m,word64 *mlen,const byte *sm,word64 n,const byte *pk
 /// \param pk public key byte buffer
 /// \param sk private key byte buffer
 /// \details crypto_sign_keypair() creates an ed25519 keypair.
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
 /// \since Crypto++ 6.0
 int crypto_sign_keypair(byte *pk, byte *sk);
 
+/// \brief Calculate a public key from a secret key
+/// \param pk public key byte buffer
+/// \param sk private key byte buffer
+/// \details crypto_sign_sk2pk() creates an ed25519 public key from an existing
+///   32-byte secret key. The function does not backfill the tail bytes of the
+///   secret key with the calculated public key.
+/// \details crypto_sign_sk2pk() is not part of libsodium or Tweet API. It was
+///   added for interop with some anonymous routing protocols.
+/// \return 0 on success, non-0 otherwise
+/// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
+/// \since Crypto++ 8.0
+int crypto_sign_sk2pk(byte *pk, const byte *sk);
+
 /// \brief Produce a keystream using XSalsa20
 /// \details crypto_stream() uses crypto_stream_xsalsa20
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/stream.html">NaCl crypto_stream documentation</A>
 /// \since Crypto++ 6.0
 int crypto_stream(byte *c,word64 d,const byte *n,const byte *k);
 
 /// \brief Encrypt a message using XSalsa20
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/stream.html">NaCl crypto_stream documentation</A>
 /// \since Crypto++ 6.0
 int crypto_stream_xor(byte *c,const byte *m,word64 d,const byte *n,const byte *k);
 
 /// \brief Produce a keystream using Salsa20
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/stream.html">NaCl crypto_stream documentation</A>
 /// \since Crypto++ 6.0
 int crypto_stream_salsa20(byte *c,word64 d,const byte *n,const byte *k);
 
 /// \brief Encrypt a message using Salsa20
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/stream.html">NaCl crypto_stream documentation</A>
 /// \since Crypto++ 6.0
 int crypto_stream_salsa20_xor(byte *c,const byte *m,word64 b,const byte *n,const byte *k);
 
 /// \brief Compare 16-byte buffers
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/verify.html">NaCl crypto_verify documentation</A>
 /// \since Crypto++ 6.0
 int crypto_verify_16(const byte *x,const byte *y);
 
 /// \brief Compare 32-byte buffers
-/// \returns 0 on success, non-0 otherwise
+/// \return 0 on success, non-0 otherwise
 /// \sa <A HREF="https://nacl.cr.yp.to/verify.html">NaCl crypto_verify documentation</A>
 /// \since Crypto++ 6.0
 int crypto_verify_32(const byte *x,const byte *y);

+ 36 - 32
include/cryptlib/nbtheory.h

@@ -13,7 +13,10 @@
 NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief The Small Prime table
-/// \details GetPrimeTable obtains pointer to small prime table and provides the size of the table.
+/// \param size number of elements in the table
+/// \return prime table with /p size elements
+/// \details GetPrimeTable() obtains pointer to small prime table and provides the size of the table.
+///  /p size is an out parameter.
 CRYPTOPP_DLL const word16 * CRYPTOPP_API GetPrimeTable(unsigned int &size);
 
 // ************ primality testing ****************
@@ -21,33 +24,33 @@ CRYPTOPP_DLL const word16 * CRYPTOPP_API GetPrimeTable(unsigned int &size);
 /// \brief Generates a provable prime
 /// \param rng a RandomNumberGenerator to produce random material
 /// \param bits the number of bits in the prime number
-/// \returns Integer() meeting Maurer's tests for primality
+/// \return Integer() meeting Maurer's tests for primality
 CRYPTOPP_DLL Integer CRYPTOPP_API MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
 
 /// \brief Generates a provable prime
 /// \param rng a RandomNumberGenerator to produce random material
 /// \param bits the number of bits in the prime number
-/// \returns Integer() meeting Mihailescu's tests for primality
+/// \return Integer() meeting Mihailescu's tests for primality
 /// \details Mihailescu's methods performs a search using algorithmic progressions.
 CRYPTOPP_DLL Integer CRYPTOPP_API MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
 
 /// \brief Tests whether a number is a small prime
 /// \param p a candidate prime to test
-/// \returns true if p is a small prime, false otherwise
+/// \return true if p is a small prime, false otherwise
 /// \details Internally, the library maintains a table of the first 32719 prime numbers
 ///   in sorted order. IsSmallPrime searches the table and returns true if p is
 ///   in the table.
 CRYPTOPP_DLL bool CRYPTOPP_API IsSmallPrime(const Integer &p);
 
 /// \brief Tests whether a number is divisible by a small prime
-/// \returns true if p is divisible by some prime less than bound.
+/// \return true if p is divisible by some prime less than bound.
 /// \details TrialDivision() returns <tt>true</tt> if <tt>p</tt> is divisible by some prime less
 ///   than <tt>bound</tt>. <tt>bound</tt> should not be greater than the largest entry in the
 ///   prime table, which is 32719.
 CRYPTOPP_DLL bool CRYPTOPP_API TrialDivision(const Integer &p, unsigned bound);
 
 /// \brief Tests whether a number is divisible by a small prime
-/// \returns true if p is NOT divisible by small primes.
+/// \return true if p is NOT divisible by small primes.
 /// \details SmallDivisorsTest() returns <tt>true</tt> if <tt>p</tt> is NOT divisible by some
 ///   prime less than 32719.
 CRYPTOPP_DLL bool CRYPTOPP_API SmallDivisorsTest(const Integer &p);
@@ -55,7 +58,7 @@ CRYPTOPP_DLL bool CRYPTOPP_API SmallDivisorsTest(const Integer &p);
 /// \brief Determine if a number is probably prime
 /// \param n the number to test
 /// \param b the base to exponentiate
-/// \returns true if the number n is probably prime, false otherwise.
+/// \return true if the number n is probably prime, false otherwise.
 /// \details IsFermatProbablePrime raises <tt>b</tt> to the <tt>n-1</tt> power and checks if
 ///   the result is congruent to 1 modulo <tt>n</tt>.
 /// \details These is no reason to use IsFermatProbablePrime, use IsStrongProbablePrime or
@@ -65,7 +68,7 @@ CRYPTOPP_DLL bool CRYPTOPP_API IsFermatProbablePrime(const Integer &n, const Int
 
 /// \brief Determine if a number is probably prime
 /// \param n the number to test
-/// \returns true if the number n is probably prime, false otherwise.
+/// \return true if the number n is probably prime, false otherwise.
 /// \details These is no reason to use IsLucasProbablePrime, use IsStrongProbablePrime or
 ///   IsStrongLucasProbablePrime instead.
 /// \sa IsStrongProbablePrime, IsStrongLucasProbablePrime
@@ -74,12 +77,12 @@ CRYPTOPP_DLL bool CRYPTOPP_API IsLucasProbablePrime(const Integer &n);
 /// \brief Determine if a number is probably prime
 /// \param n the number to test
 /// \param b the base to exponentiate
-/// \returns true if the number n is probably prime, false otherwise.
+/// \return true if the number n is probably prime, false otherwise.
 CRYPTOPP_DLL bool CRYPTOPP_API IsStrongProbablePrime(const Integer &n, const Integer &b);
 
 /// \brief Determine if a number is probably prime
 /// \param n the number to test
-/// \returns true if the number n is probably prime, false otherwise.
+/// \return true if the number n is probably prime, false otherwise.
 CRYPTOPP_DLL bool CRYPTOPP_API IsStrongLucasProbablePrime(const Integer &n);
 
 /// \brief Determine if a number is probably prime
@@ -94,7 +97,7 @@ CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng, const
 
 /// \brief Verifies a number is probably prime
 /// \param p a candidate prime to test
-/// \returns true if p is a probable prime, false otherwise
+/// \return true if p is a probable prime, false otherwise
 /// \details IsPrime() is suitable for testing candidate primes when creating them. Internally,
 ///   IsPrime() utilizes SmallDivisorsTest(), IsStrongProbablePrime() and IsStrongLucasProbablePrime().
 CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p);
@@ -103,9 +106,9 @@ CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p);
 /// \param rng a RandomNumberGenerator for randomized testing
 /// \param p a candidate prime to test
 /// \param level the level of thoroughness of testing
-/// \returns true if p is a strong probable prime, false otherwise
+/// \return true if p is a strong probable prime, false otherwise
 /// \details VerifyPrime() is suitable for testing candidate primes created by others. Internally,
-///   VerifyPrime() utilizes IsPrime() and one-round RabinMillerTest(). If the candiate passes and
+///   VerifyPrime() utilizes IsPrime() and one-round RabinMillerTest(). If the candidate passes and
 ///   level is greater than 1, then 10 round RabinMillerTest() primality testing is performed.
 CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1);
 
@@ -113,6 +116,7 @@ CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Int
 class CRYPTOPP_DLL PrimeSelector
 {
 public:
+	virtual ~PrimeSelector() {}
 	const PrimeSelector *GetSelectorPointer() const {return this;}
 	virtual bool IsAcceptable(const Integer &candidate) const =0;
 };
@@ -123,7 +127,7 @@ public:
 /// \param equiv the equivalence class based on the parameter mod
 /// \param mod the modulus used to reduce the equivalence class
 /// \param pSelector pointer to a PrimeSelector function for the application to signal suitability
-/// \returns true if and only if FirstPrime() finds a prime and returns the prime through p. If FirstPrime()
+/// \return true if and only if FirstPrime() finds a prime and returns the prime through p. If FirstPrime()
 ///   returns false, then no such prime exists and the value of p is undefined
 /// \details FirstPrime() uses a fast sieve to find the first probable prime
 ///   in <tt>{x | p<=x<=max and x%mod==equiv}</tt>
@@ -138,28 +142,28 @@ CRYPTOPP_DLL AlgorithmParameters CRYPTOPP_API MakeParametersForTwoPrimesOfEqualS
 /// \brief Calculate the greatest common divisor
 /// \param a the first term
 /// \param b the second term
-/// \returns the greatest common divisor if one exists, 0 otherwise.
+/// \return the greatest common divisor if one exists, 0 otherwise.
 inline Integer GCD(const Integer &a, const Integer &b)
 	{return Integer::Gcd(a,b);}
 
 /// \brief Determine relative primality
 /// \param a the first term
 /// \param b the second term
-/// \returns true if <tt>a</tt> and <tt>b</tt> are relatively prime, false otherwise.
+/// \return true if <tt>a</tt> and <tt>b</tt> are relatively prime, false otherwise.
 inline bool RelativelyPrime(const Integer &a, const Integer &b)
 	{return Integer::Gcd(a,b) == Integer::One();}
 
 /// \brief Calculate the least common multiple
 /// \param a the first term
 /// \param b the second term
-/// \returns the least common multiple of <tt>a</tt> and <tt>b</tt>.
+/// \return the least common multiple of <tt>a</tt> and <tt>b</tt>.
 inline Integer LCM(const Integer &a, const Integer &b)
 	{return a/Integer::Gcd(a,b)*b;}
 
 /// \brief Calculate multiplicative inverse
 /// \param a the number to test
 /// \param b the modulus
-/// \returns an Integer <tt>(a ^ -1) % n</tt> or 0 if none exists.
+/// \return an Integer <tt>(a ^ -1) % n</tt> or 0 if none exists.
 /// \details EuclideanMultiplicativeInverse returns the multiplicative inverse of the Integer
 ///   <tt>*a</tt> modulo the Integer <tt>b</tt>. If no Integer exists then Integer 0 is returned.
 inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
@@ -172,7 +176,7 @@ inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b
 /// \param xq the second number, mod q
 /// \param q the second prime modulus
 /// \param u inverse of p mod q
-/// \returns the CRT value of the parameters
+/// \return the CRT value of the parameters
 /// \details CRT uses the Chinese Remainder Theorem to calculate <tt>x</tt> given
 ///   <tt>x mod p</tt> and <tt>x mod q</tt>, and <tt>u</tt> the inverse of <tt>p mod q</tt>.
 CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u);
@@ -180,7 +184,7 @@ CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const
 /// \brief Calculate the Jacobi symbol
 /// \param a the first term
 /// \param b the second term
-/// \returns the the Jacobi symbol.
+/// \return the Jacobi symbol.
 /// \details Jacobi symbols are calculated using the following rules:
 ///  -# if <tt>b</tt> is prime, then <tt>Jacobi(a, b)</tt>, then return 0
 ///  -# if <tt>a%b</tt>==0 AND <tt>a</tt> is quadratic residue <tt>mod b</tt>, then return 1
@@ -189,12 +193,12 @@ CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const
 CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b);
 
 /// \brief Calculate the Lucas value
-/// \returns the Lucas value
+/// \return the Lucas value
 /// \details Lucas() calculates the Lucas function <tt>V_e(p, 1) mod n</tt>.
 CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n);
 
 /// \brief Calculate the inverse Lucas value
-/// \returns the inverse Lucas value
+/// \return the inverse Lucas value
 /// \details InverseLucas() calculates <tt>x</tt> such that <tt>m==Lucas(e, x, p*q)</tt>,
 ///   <tt>p q</tt> primes, <tt>u</tt> is inverse of <tt>p mod q</tt>.
 CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u);
@@ -203,7 +207,7 @@ CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &
 /// \param x the first term
 /// \param y the second term
 /// \param m the modulus
-/// \returns an Integer <tt>(x * y) % m</tt>.
+/// \return an Integer <tt>(x * y) % m</tt>.
 inline Integer ModularMultiplication(const Integer &x, const Integer &y, const Integer &m)
 	{return a_times_b_mod_c(x, y, m);}
 
@@ -211,19 +215,19 @@ inline Integer ModularMultiplication(const Integer &x, const Integer &y, const I
 /// \param x the base
 /// \param e the exponent
 /// \param m the modulus
-/// \returns an Integer <tt>(a ^ b) % m</tt>.
+/// \return an Integer <tt>(a ^ b) % m</tt>.
 inline Integer ModularExponentiation(const Integer &x, const Integer &e, const Integer &m)
 	{return a_exp_b_mod_c(x, e, m);}
 
 /// \brief Extract a modular square root
 /// \param a the number to extract square root
 /// \param p the prime modulus
-/// \returns the modular square root if it exists
+/// \return the modular square root if it exists
 /// \details ModularSquareRoot returns <tt>x</tt> such that <tt>x*x%p == a</tt>, <tt>p</tt> prime
 CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p);
 
 /// \brief Extract a modular root
-/// \returns a modular root if it exists
+/// \return a modular root if it exists
 /// \details ModularRoot returns <tt>x</tt> such that <tt>a==ModularExponentiation(x, e, p*q)</tt>,
 ///   <tt>p</tt> <tt>q</tt> primes, and <tt>e</tt> relatively prime to <tt>(p-1)*(q-1)</tt>,
 ///   <tt>dp=d%(p-1)</tt>, <tt>dq=d%(q-1)</tt>, (d is inverse of <tt>e mod (p-1)*(q-1)</tt>)
@@ -237,21 +241,21 @@ CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &d
 /// \param b the second coefficient
 /// \param c the third constant
 /// \param p the prime modulus
-/// \returns true if solutions exist
+/// \return true if solutions exist
 /// \details SolveModularQuadraticEquation() finds <tt>r1</tt> and <tt>r2</tt> such that <tt>ax^2 +
 ///   bx + c == 0 (mod p)</tt> for x in <tt>{r1, r2}</tt>, <tt>p</tt> prime.
 CRYPTOPP_DLL bool CRYPTOPP_API SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p);
 
 /// \brief Estimate work factor
 /// \param bitlength the size of the number, in bits
-/// \returns the estimated work factor, in operations
+/// \return the estimated work factor, in operations
 /// \details DiscreteLogWorkFactor returns log base 2 of estimated number of operations to
 ///   calculate discrete log or factor a number.
 CRYPTOPP_DLL unsigned int CRYPTOPP_API DiscreteLogWorkFactor(unsigned int bitlength);
 
 /// \brief Estimate work factor
 /// \param bitlength the size of the number, in bits
-/// \returns the estimated work factor, in operations
+/// \return the estimated work factor, in operations
 /// \details FactoringWorkFactor returns log base 2 of estimated number of operations to
 ///   calculate discrete log or factor a number.
 CRYPTOPP_DLL unsigned int CRYPTOPP_API FactoringWorkFactor(unsigned int bitlength);
@@ -296,15 +300,15 @@ public:
 	void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits);
 
 	/// \brief Retrieve first prime
-	/// \returns Prime() returns the prime p.
+	/// \return Prime() returns the prime p.
 	const Integer& Prime() const {return p;}
 
 	/// \brief Retrieve second prime
-	/// \returns SubPrime() returns the prime q.
+	/// \return SubPrime() returns the prime q.
 	const Integer& SubPrime() const {return q;}
 
 	/// \brief Retrieve the generator
-	/// \returns Generator() returns the the generator g.
+	/// \return Generator() returns the generator g.
 	const Integer& Generator() const {return g;}
 
 private:

+ 5 - 0
include/cryptlib/nr.h

@@ -1,3 +1,8 @@
+// nr.h - originally written and placed in the public domain by Wei Dai
+
+/// \file nr.h
+/// \brief Classes for Nyberg-Rueppel signature scheme
+
 #ifndef CRYPTOPP_NR_H
 #define CRYPTOPP_NR_H
 

+ 45 - 4
include/cryptlib/oids.h

@@ -1,7 +1,7 @@
 // oids.h - originally written and placed in the public domain by Wei Dai
 
 /// \file oids.h
-/// \brief ASN.1 object identifiers for algorthms and schemes
+/// \brief ASN.1 object identifiers for algorithms and schemes
 /// \details Most OIDs can be found at http://www.oid-info.com/. The Chinese OIDs
 ///   are assigned in GM/T 0006-2012, Cryptographic Application Identifier Criterion
 ///   Specification. A reproduction can be found at http://gmssl.org/docs/oid.html.
@@ -34,7 +34,8 @@ DEFINE_OID(1, iso)
 							DEFINE_OID(sm2encrypt()+2, sm2encrypt_specifiedParameters)
 		DEFINE_OID(member_body()+840, iso_us)
 			DEFINE_OID(iso_us()+10040, ansi_x9_57)
-				DEFINE_OID(ansi_x9_57()+4+1, id_dsa)
+				DEFINE_OID(ansi_x9_57()+4, ansi_x9cm)
+					DEFINE_OID(ansi_x9cm()+1, id_dsa)
 			DEFINE_OID(iso_us()+10045, ansi_x9_62)
 				DEFINE_OID(ansi_x9_62()+1, id_fieldType)
 					DEFINE_OID(id_fieldType()+1, prime_field)
@@ -47,17 +48,44 @@ DEFINE_OID(1, iso)
 					DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey)
 				DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves)
 					DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime)
-						DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1)
-						DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1)
+						// ANSI X9.62
+						DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1)  // secp192v1
+						//DEFINE_OID(ansi_x9_62_curves_prime()+2, secp192v2)
+						//DEFINE_OID(ansi_x9_62_curves_prime()+3, secp192v3)
+						//DEFINE_OID(ansi_x9_62_curves_prime()+4, secp239v1)
+						//DEFINE_OID(ansi_x9_62_curves_prime()+5, secp239v2)
+						//DEFINE_OID(ansi_x9_62_curves_prime()+6, secp239v3)
+						DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1)  // secp256v1
+				DEFINE_OID(ansi_x9_62()+4, ansi_signatures)
+						DEFINE_OID(ansi_signatures()+3, ecdsa_with_sha2)
+							DEFINE_OID(ecdsa_with_sha2()+1, ecdsa_with_sha224)
+							DEFINE_OID(ecdsa_with_sha2()+2, ecdsa_with_sha256)
+							DEFINE_OID(ecdsa_with_sha2()+3, ecdsa_with_sha384)
+							DEFINE_OID(ecdsa_with_sha2()+4, ecdsa_with_sha512)
 			DEFINE_OID(iso_us()+113549, rsadsi)
 				DEFINE_OID(rsadsi()+1, pkcs)
 					DEFINE_OID(pkcs()+1, pkcs_1)
+						// Arc from PKCS #1 and RFC 2459
 						DEFINE_OID(pkcs_1()+1, rsaEncryption)
+						DEFINE_OID(pkcs_1()+2, md2WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+3, md4withRSAEncryption)
+						DEFINE_OID(pkcs_1()+4, md5WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+5, sha1WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+10, rsassa_pss)
+						DEFINE_OID(pkcs_1()+11, sha256WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+12, sha384WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+13, sha512WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+14, sha224WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+15, sha512_224WithRSAEncryption)
+						DEFINE_OID(pkcs_1()+16, sha512_256WithRSAEncryption)
 				DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm)
 					DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2)
 					DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5)
 	DEFINE_OID(iso()+3, identified_organization)
 		// Arc from http://tools.ietf.org/html/draft-josefsson-pkix-newcurves
+		// GNU and OpenPGP uses 1.3.6.1.4.1.11591.15.1 for Ed25519. See
+		// https://www.gnu.org/prep/standards/html_node/OID-Allocations.html,
+		// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-rfc4880bis
 		DEFINE_OID(identified_organization()+6, dod)
 			DEFINE_OID(dod()+1, internet)
 				DEFINE_OID(internet()+4, internet_private)
@@ -72,6 +100,10 @@ DEFINE_OID(1, iso)
 			DEFINE_OID(oiw()+3, oiw_secsig)
 				DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms)
 					DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1)
+			DEFINE_OID(oiw()+7, dssig)
+				DEFINE_OID(dssig()+2, algorithm)
+					DEFINE_OID(algorithm()+1, encryptionAlgorithm)
+						DEFINE_OID(encryptionAlgorithm()+1, elGamal)
 		DEFINE_OID(identified_organization()+36, teletrust)
 			DEFINE_OID(teletrust()+3, teletrust_algorithm)
 				DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160)
@@ -83,6 +115,12 @@ DEFINE_OID(1, iso)
 					DEFINE_OID(teletrust_ellipticCurve()+1+9, brainpoolP320r1)
 					DEFINE_OID(teletrust_ellipticCurve()+1+11, brainpoolP384r1)
 					DEFINE_OID(teletrust_ellipticCurve()+1+13, brainpoolP512r1)
+		// https://tools.ietf.org/html/draft-ietf-curdle-pkix-07
+		DEFINE_OID(identified_organization()+101, thawte)
+			DEFINE_OID(thawte()+110, X25519)
+			DEFINE_OID(thawte()+111, X448)
+			DEFINE_OID(thawte()+112, Ed25519)
+			DEFINE_OID(thawte()+113, Ed448)
 		DEFINE_OID(identified_organization()+132, certicom)
 			DEFINE_OID(certicom()+0, certicom_ellipticCurve)
 				// these are sorted by curve type and then by OID
@@ -148,6 +186,9 @@ DEFINE_OID(2, joint_iso_ccitt)
 								DEFINE_OID(nist_hashalgs()+8, id_sha3_256)
 								DEFINE_OID(nist_hashalgs()+9, id_sha3_384)
 								DEFINE_OID(nist_hashalgs()+10, id_sha3_512)
+			DEFINE_OID(joint_iso_ccitt_us()+10046, ansi_x942)
+				DEFINE_OID(ansi_x942()+2, number_type)
+					DEFINE_OID(number_type()+1, dhpublicnumber)
 
 NAMESPACE_END
 

+ 69 - 42
include/cryptlib/osrng.h

@@ -14,6 +14,7 @@
 #include "randpool.h"
 #include "smartptr.h"
 #include "fips140.h"
+#include "hkdf.h"
 #include "rng.h"
 #include "aes.h"
 #include "sha.h"
@@ -56,23 +57,23 @@ public:
 #endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI
 
 	/// \brief Retrieves the provider handle
-	/// \returns CryptoAPI provider handle
+	/// \return CryptoAPI provider handle
 	/// \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext()
-	///   acquires then handle and CryptReleaseContext() releases the handle
-	///   upon destruction. If USE_MS_CNGAPI is in effect, then
-	///   BCryptOpenAlgorithmProvider() acquires then handle and
-	///   BCryptCloseAlgorithmProvider() releases the handle upon destruction.
+	///  acquires then handle and CryptReleaseContext() releases the handle
+	///  upon destruction. If USE_MS_CNGAPI is in effect, then
+	///  BCryptOpenAlgorithmProvider() acquires then handle and
+	///  BCryptCloseAlgorithmProvider() releases the handle upon destruction.
 	ProviderHandle GetProviderHandle() const {return m_hProvider;}
 
 private:
 	ProviderHandle m_hProvider;
 };
 
-#if defined(_MSC_VER) && defined(USE_MS_CRYPTOAPI)
+#if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CRYPTOAPI)
 # pragma comment(lib, "advapi32.lib")
 #endif
 
-#if defined(_MSC_VER) && defined(USE_MS_CNGAPI)
+#if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CNGAPI)
 # pragma comment(lib, "bcrypt.lib")
 #endif
 
@@ -80,7 +81,7 @@ private:
 
 /// \brief Wrapper class for /dev/random and /dev/srandom
 /// \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom()
-///   on Windows, or /dev/urandom on Unix and compatibles.
+///  on Windows, or /dev/urandom on Unix and compatibles.
 class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
 {
 public:
@@ -112,9 +113,9 @@ protected:
 /// \brief Wrapper class for /dev/random and /dev/srandom
 /// \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.
 /// \note On Linux the /dev/random interface is effectively deprecated. According to the
-///   Kernel Crypto developers, /dev/urandom or getrandom(2) should be used instead. Also
-///   see <A HREF="https://lkml.org/lkml/2017/7/20/993">[RFC PATCH v12 3/4] Linux Random
-///   Number Generator</A> on the kernel-crypto mailing list.
+///  Kernel Crypto developers, /dev/urandom or getrandom(2) should be used instead. Also
+///  see <A HREF="https://lkml.org/lkml/2017/7/20/993">[RFC PATCH v12 3/4] Linux Random
+///  Number Generator</A> on the kernel-crypto mailing list.
 class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
 {
 public:
@@ -139,19 +140,21 @@ protected:
 
 /// OS_GenerateRandomBlock
 /// \brief Generate random array of bytes
-/// \param blocking specifies whther a bobcking or non-blocking generator should be used
+/// \param blocking specifies whether a blocking or non-blocking generator should be used
 /// \param output the byte buffer
 /// \param size the length of the buffer, in bytes
 /// \details OS_GenerateRandomBlock() uses the underlying operating system's
-///   random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
+///  random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
 /// \details On Unix and compatibles, /dev/urandom is called if blocking is false using
-///   NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
+///  NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
 ///  by way of BlockingRng, if available.
 CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
 
 /// \brief Automatically Seeded Randomness Pool
 /// \details This class seeds itself using an operating system provided RNG.
-///    AutoSeededRandomPool was suggested by Leonard Janke.
+///  AutoSeededRandomPool was suggested by Leonard Janke.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
 {
 public:
@@ -163,7 +166,7 @@ public:
 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
 	/// \param seedSize the size of the seed, in bytes
 	/// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
-	///   The parameter is ignored if only one of these is available.
+	///  The parameter is ignored if only one of these is available.
 	explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
 		{Reseed(blocking, seedSize);}
 
@@ -176,16 +179,20 @@ public:
 /// \tparam BLOCK_CIPHER a block cipher
 /// \brief Automatically Seeded X9.17 RNG
 /// \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.
-///   If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
-///   used, then its a X9.31 conforming generator.
-/// \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER can be any
-///   BlockTransformation derived class.
+///  If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
+///  used, then its a X9.31 conforming generator.
+/// \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER
+///  can be any BlockTransformation derived class.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 /// \sa X917RNG, DefaultAutoSeededRNG
 template <class BLOCK_CIPHER>
 class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
 {
 public:
-	static std::string StaticAlgorithmName() { return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")"); }
+	static std::string StaticAlgorithmName() {
+		return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")");
+	}
 
 	~AutoSeededX917RNG() {}
 
@@ -193,19 +200,19 @@ public:
 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
 	/// \param autoSeed controls auto seeding of the generator
 	/// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
-	///   The parameter is ignored if only one of these is available.
+	///  The parameter is ignored if only one of these is available.
 	/// \sa X917RNG
 	explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
 		{if (autoSeed) Reseed(blocking);}
 
 	/// \brief Reseed an AutoSeededX917RNG
 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
-	/// \param additionalEntropy additional entropy to add to the generator
+	/// \param input additional entropy to add to the generator
 	/// \param length the size of the additional entropy, in bytes
 	/// \details Internally, the generator uses SHA256 to extract the entropy from
-	///   from the seed and then stretch the material for the block cipher's key
-	///   and initialization vector.
-	void Reseed(bool blocking = false, const byte *additionalEntropy = NULLPTR, size_t length = 0);
+	///  from the seed and then stretch the material for the block cipher's key
+	///  and initialization vector.
+	void Reseed(bool blocking = false, const byte *input = NULLPTR, size_t length = 0);
 
 	/// \brief Deterministically reseed an AutoSeededX917RNG for testing
 	/// \param key the key to use for the deterministic reseeding
@@ -213,7 +220,7 @@ public:
 	/// \param seed the seed to use for the deterministic reseeding
 	/// \param timeVector a time vector to use for deterministic reseeding
 	/// \details This is a testing interface for testing purposes, and should \a NOT
-	///   be used in production.
+	///  be used in production.
 	void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
 
 	bool CanIncorporateEntropy() const {return true;}
@@ -221,6 +228,8 @@ public:
 	void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
 		{m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
 
+	std::string AlgorithmProvider() const;
+
 private:
 	member_ptr<RandomNumberGenerator> m_rng;
 };
@@ -234,23 +243,39 @@ void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength,
 template <class BLOCK_CIPHER>
 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
 {
-	SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
-	const byte *key;
+	enum {BlockSize=BLOCK_CIPHER::BLOCKSIZE};
+	enum {KeyLength=BLOCK_CIPHER::DEFAULT_KEYLENGTH};
+	enum {SeedSize=EnumToInt(BlockSize)+EnumToInt(KeyLength)};
+
+	SecByteBlock seed(SeedSize), temp(SeedSize);
+	const byte label[] = "X9.17 key generation";
+	const byte *key=NULLPTR;
+
 	do
 	{
-		OS_GenerateRandomBlock(blocking, seed, seed.size());
-		if (length > 0)
-		{
-			SHA256 hash;
-			hash.Update(seed, seed.size());
-			hash.Update(input, length);
-			hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size()));
-		}
-		key = seed + BLOCK_CIPHER::BLOCKSIZE;
+		OS_GenerateRandomBlock(blocking, temp, temp.size());
+
+		HKDF<SHA256> hkdf;
+		hkdf.DeriveKey(
+			seed, seed.size(),  // derived secret
+			temp, temp.size(),  // instance secret
+			input, length,      // user secret
+			label, 20           // unique label
+		);
+
+		key = seed + BlockSize;
 	}	// check that seed and key don't have same value
-	while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);
+	while (std::memcmp(key, seed, STDMIN((size_t)BlockSize, (size_t)KeyLength)) == 0);
 
-	Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULLPTR);
+	Reseed(key, KeyLength, seed, NULLPTR);
+}
+
+template <class BLOCK_CIPHER>
+std::string AutoSeededX917RNG<BLOCK_CIPHER>::AlgorithmProvider() const
+{
+	// Hack for now... We need to instantiate one
+	typename BLOCK_CIPHER::Encryption bc;
+	return bc.AlgorithmProvider();
 }
 
 CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
@@ -258,8 +283,10 @@ CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
 /// \brief A typedef providing a default generator
 /// \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.
-///   If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
-///   AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
+///  If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
+///  AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
+/// \details You should reseed the generator after a fork() to avoid multiple generators
+///  with the same internal state.
 class DefaultAutoSeededRNG {}
 #else
 // AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool

+ 22 - 22
include/cryptlib/ossig.h

@@ -29,8 +29,8 @@ extern "C" {
 /// \brief Null signal handler function
 /// \param unused the signal number
 /// \details NullSignalHandler is provided as a stand alone function with external "C" linkage
-///   and not a static member function due to the the member function's implicit
-///   external "C++" linkage.
+///  and not a static member function due to the member function's implicit
+///  external "C++" linkage.
 /// \sa SignalHandler, SignalHandlerFn
 extern "C" {
     inline void NullSignalHandler(int unused) {CRYPTOPP_UNUSED(unused);}
@@ -38,20 +38,20 @@ extern "C" {
 
 /// Signal handler for Linux and Unix compatibles
 /// \tparam S Signal number
-/// \tparam O Flag indicating exsting handler should be overwriiten
+/// \tparam O Flag indicating if an existing handler should be overwritten
 /// \details SignalHandler() can be used to install a signal handler with the signature
-///   <tt>void handler_fn(int)</tt>. If <tt>SignalHandlerFn</tt> is not <tt>NULL</tt>, then
-///   the sigaction is set to the function and the sigaction flags is set to the flags.
-///   If <tt>SignalHandlerFn</tt> is <tt>NULL</tt>, then a default handler is installed
-///   using sigaction flags set to 0. The default handler only returns from the call.
+///  <tt>void handler_fn(int)</tt>. If <tt>SignalHandlerFn</tt> is not <tt>NULL</tt>, then
+///  the sigaction is set to the function and the sigaction flags is set to the flags.
+///  If <tt>SignalHandlerFn</tt> is <tt>NULL</tt>, then a default handler is installed
+///  using sigaction flags set to 0. The default handler only returns from the call.
 /// \details Upon destruction the previous signal handler is restored if the former signal handler
-///   was replaced.
+///  was replaced.
 /// \details On Cygwin systems using Newlib, you should define <tt>_XOPEN_SOURCE=700</tt> or
-///   <tt>_GNU_SOURCE</tt>; or use <tt>-std=gnu++03</tt>, <tt>-std=gnu++11</tt>, or similar. If
-///   you compile with <tt>-std=c++03</tt>, <tt>-std=c++11</tt> or similar, then define
-///   <tt>_XOPEN_SOURCE=700</tt>.
+///  <tt>_GNU_SOURCE</tt>; or use <tt>-std=gnu++03</tt>, <tt>-std=gnu++11</tt>, or similar. If
+///  you compile with <tt>-std=c++03</tt>, <tt>-std=c++11</tt> or similar, then define
+///  <tt>_XOPEN_SOURCE=700</tt>.
 /// \warning Do not use SignalHandler in a code block that uses <tt>setjmp</tt> or <tt>longjmp</tt>
-///   because the destructor may not run.
+///  because the destructor may not run.
 /// \since Crypto++ 5.6.5
 /// \sa NullSignalHandler, SignalHandlerFn, \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", DebugTrapHandler
 template <int S, bool O=false>
@@ -61,19 +61,19 @@ struct SignalHandler
     /// \param pfn Pointer to a signal handler function
     /// \param flags Flags to use with the signal handler
     /// \details SignalHandler() installs a signal handler with the signature
-    ///   <tt>void handler_fn(int)</tt>. If <tt>SignalHandlerFn</tt> is not <tt>NULL</tt>, then
-    ///   the sigaction is set to the function and the sigaction flags is set to the flags.
-    ///   If <tt>SignalHandlerFn</tt> is <tt>NULL</tt>, then a default handler is installed
-    ///   using sigaction flags set to 0. The default handler only returns from the call.
+    ///  <tt>void handler_fn(int)</tt>. If <tt>SignalHandlerFn</tt> is not <tt>NULL</tt>, then
+    ///  the sigaction is set to the function and the sigaction flags is set to the flags.
+    ///  If <tt>SignalHandlerFn</tt> is <tt>NULL</tt>, then a default handler is installed
+    ///  using sigaction flags set to 0. The default handler only returns from the call.
     /// \details Upon destruction the previous signal handler is restored if the former signal handler
-    ///   was overwritten.
+    ///  was overwritten.
     /// \details On Cygwin systems using Newlib, you should define <tt>_XOPEN_SOURCE=700</tt> or
-    ///   <tt>_GNU_SOURCE</tt>; or use <tt>-std=gnu++03</tt>, <tt>-std=gnu++11</tt>, or similar. If
-    ///   you compile with <tt>-std=c++03</tt>, <tt>-std=c++11</tt> or similar, then define
-    ///   <tt>_XOPEN_SOURCE=700</tt>.
+    ///  <tt>_GNU_SOURCE</tt>; or use <tt>-std=gnu++03</tt>, <tt>-std=gnu++11</tt>, or similar. If
+    ///  you compile with <tt>-std=c++03</tt>, <tt>-std=c++11</tt> or similar, then define
+    ///  <tt>_XOPEN_SOURCE=700</tt>.
     /// \warning Do not use SignalHandler in a code block that uses <tt>setjmp</tt> or <tt>longjmp</tt>
-    ///   because the destructor may not run. <tt>setjmp</tt> is why cpu.cpp does not use SignalHandler
-    ///   during CPU feature testing.
+    ///  because the destructor may not run. <tt>setjmp</tt> is why cpu.cpp does not use SignalHandler
+    ///  during CPU feature testing.
     /// \since Crypto++ 5.6.5
     SignalHandler(SignalHandlerFn pfn = NULLPTR, int flags = 0) : m_installed(false)
     {

+ 5 - 3
include/cryptlib/padlkrng.h

@@ -96,9 +96,11 @@ public:
 		CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
 	}
 
+    std::string AlgorithmProvider() const;
+
 	/// \brief Set the XSTORE divisor
 	/// \param divisor the XSTORE divisor
-	/// \returns the old XSTORE divisor
+	/// \return the old XSTORE divisor
 	word32 SetDivisor(word32 divisor)
 	{
 		word32 old = m_divisor;
@@ -107,14 +109,14 @@ public:
 	}
 
 	/// \brief Get the XSTORE divisor
-	/// \returns the current XSTORE divisor
+	/// \return the current XSTORE divisor
 	word32 GetDivisor() const
 	{
 		return m_divisor;
 	}
 
 	/// \brief Get the MSR for the last operation
-	/// \returns the MSR for the last read operation
+	/// \return the MSR for the last read operation
 	word32 GetMSR() const
 	{
 		return m_msr;

+ 17 - 5
include/cryptlib/panama.h

@@ -11,9 +11,12 @@
 #include "secblock.h"
 
 // Clang 3.3 integrated assembler crash on Linux. Clang 3.4 due to compiler error with .intel_syntax
-#if CRYPTOPP_BOOL_X32 || defined(CRYPTOPP_DISABLE_INTEL_ASM)
-# define CRYPTOPP_DISABLE_PANAMA_ASM
-#endif
+//#if CRYPTOPP_BOOL_X32 || defined(CRYPTOPP_DISABLE_MIXED_ASM)
+//# define CRYPTOPP_DISABLE_PANAMA_ASM
+//#endif
+
+// https://github.com/weidai11/cryptopp/issues/758
+#define CRYPTOPP_DISABLE_PANAMA_ASM 1
 
 NAMESPACE_BEGIN(CryptoPP)
 
@@ -22,12 +25,14 @@ template <class B>
 class CRYPTOPP_NO_VTABLE Panama
 {
 public:
+	virtual ~Panama() {}
+	std::string AlgorithmProvider() const;
 	void Reset();
 	void Iterate(size_t count, const word32 *p=NULLPTR, byte *output=NULLPTR, const byte *input=NULLPTR, KeystreamOperation operation=WRITE_KEYSTREAM);
 
 protected:
 	typedef word32 Stage[8];
-	CRYPTOPP_CONSTANT(STAGES = 32)
+	CRYPTOPP_CONSTANT(STAGES = 32);
 
 	FixedSizeAlignedSecBlock<word32, 20 + 8*32> m_state;
 };
@@ -39,17 +44,21 @@ template <class B = LittleEndian>
 class PanamaHash : protected Panama<B>, public AlgorithmImpl<IteratedHash<word32, NativeByteOrder, 32>, PanamaHash<B> >
 {
 public:
-	CRYPTOPP_CONSTANT(DIGESTSIZE = 32)
+	CRYPTOPP_CONSTANT(DIGESTSIZE = 32);
+	virtual ~PanamaHash() {}
 	PanamaHash() {Panama<B>::Reset();}
 	unsigned int DigestSize() const {return DIGESTSIZE;}
 	void TruncatedFinal(byte *hash, size_t size);
 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == BIG_ENDIAN_ORDER ? "Panama-BE" : "Panama-LE";}
+	std::string AlgorithmProvider() const {return Panama<B>::AlgorithmProvider();} // Fix https://github.com/weidai11/cryptopp/issues/801
 
 protected:
 	void Init() {Panama<B>::Reset();}
 	void HashEndianCorrectedBlock(const word32 *data) {this->Iterate(1, data);}	// push
 	size_t HashMultipleBlocks(const word32 *input, size_t length);
 	word32* StateBuf() {return NULLPTR;}
+
+	FixedSizeSecBlock<word32, 8> m_buf;
 };
 }
 
@@ -134,6 +143,8 @@ class PanamaCipherPolicy : public AdditiveCipherConcretePolicy<word32, 8>,
 							protected Panama<B>
 {
 protected:
+	virtual ~PanamaCipherPolicy() {}
+	std::string AlgorithmProvider() const;
 	void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
 	void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
 	bool CipherIsRandomAccess() const {return false;}
@@ -141,6 +152,7 @@ protected:
 	unsigned int GetAlignment() const;
 
 	FixedSizeSecBlock<word32, 8> m_key;
+	FixedSizeSecBlock<word32, 8> m_buf;
 };
 
 /// \brief Panama stream cipher

+ 121 - 47
include/cryptlib/poly1305.h

@@ -1,45 +1,26 @@
 // poly1305.h - written and placed in the public domain by Jeffrey Walton and Jean-Pierre Munch
-//              Based on Andy Polyakov's Base-2^26 scalar multiplication implementation for OpenSSL.
+//              Based on Andy Polyakov's Base-2^26 scalar multiplication implementation.
+//              For more information, see https://www.openssl.org/~appro/cryptogams/.
+
+// The library added Bernstein's Poly1305 classes at Crypto++ 6.0. The IETF
+// uses a slightly different implementation than Bernstein, and the IETF
+// classes were added at Crypto++ 8.1. We wanted to maintain ABI compatibility
+// at the 8.1 release so the original Poly1305 classes were not disturbed.
+// Instead new classes were added for IETF Poly1305. The back-end implementation
+// shares code as expected, however.
 
 /// \file poly1305.h
 /// \brief Classes for Poly1305 message authentication code
 /// \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide
 ///   variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length
 ///   message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce.
-/// \details Each message must use a unique security context, which means either the key or nonce
-///   must be changed after each message. It can be accomplished in one of two ways. First, you
-///   can create a new Poly1305 object with a key and nonce each time its needed.
-///   <pre>  SecByteBlock key(32), nonce(16);
-///   prng.GenerateBlock(key, key.size());
-///   prng.GenerateBlock(nonce, nonce.size());
-///
-///   Poly1305<AES> poly1305(key, key.size(), nonce, nonce.size());
-///   poly1305.Update(...);
-///   poly1305.Final(...);</pre>
-///
-/// \details Second, you can create a Poly1305 object, reuse the key, and set a fresh nonce
-///   for each message. The second and subsequent nonces can be generated directly using a
-///   RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
-///   <pre>  SecByteBlock key(32), nonce(16);
-///   prng.GenerateBlock(key, key.size());
-///   prng.GenerateBlock(nonce, nonce.size());
-///
-///   // First message
-///   Poly1305<AES> poly1305(key, key.size());
-///   poly1305.Resynchronize(nonce);
-///   poly1305.Update(...);
-///   poly1305.Final(...);
-///
-///   // Second message
-///   poly1305.GetNextIV(prng, nonce);
-///   poly1305.Resynchronize(nonce);
-///   poly1305.Update(...);
-///   poly1305.Final(...);
-///   ...</pre>
+/// \details Crypto++ also supplies the IETF's version of Poly1305. It is a slightly different
+///   algorithm than Bernstein's version.
 /// \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES
-///   Message-Authentication Code (20050329)</A> and Andy Polyakov <A
+///   Message-Authentication Code (20050329)</A>, <a href="http://tools.ietf.org/html/rfc8439">RFC
+///   8439, ChaCha20 and Poly1305 for IETF Protocols</a> and Andy Polyakov <A
 ///   HREF="http://www.openssl.org/blog/blog/2016/02/15/poly1305-revised/">Poly1305 Revised</A>
-/// \since Crypto++ 6.0
+/// \since Poly1305 since Crypto++ 6.0, Poly1305TLS since Crypto++ 8.1
 
 #ifndef CRYPTOPP_POLY1305_H
 #define CRYPTOPP_POLY1305_H
@@ -52,8 +33,11 @@
 
 NAMESPACE_BEGIN(CryptoPP)
 
+////////////////////////////// Bernstein Poly1305 //////////////////////////////
+
 /// \brief Poly1305 message authentication code base class
-/// \tparam T class derived from BlockCipherDocumentation with 16-byte key and 16-byte blocksize
+/// \tparam T BlockCipherDocumentation derived class with 16-byte key and 16-byte blocksize
+/// \details Poly1305_Base is the base class of Bernstein's Poly1305 algorithm.
 /// \since Crypto++ 6.0
 template <class T>
 class CRYPTOPP_NO_VTABLE Poly1305_Base : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 16>, public MessageAuthenticationCode
@@ -64,9 +48,10 @@ class CRYPTOPP_NO_VTABLE Poly1305_Base : public FixedKeyLength<32, SimpleKeyingI
 public:
 	static std::string StaticAlgorithmName() {return std::string("Poly1305(") + T::StaticAlgorithmName() + ")";}
 
-	CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
-	CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
+	CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE);
+	CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE);
 
+	virtual ~Poly1305_Base() {}
 	Poly1305_Base() : m_idx(0), m_used(true) {}
 
 	void Resynchronize (const byte *iv, int ivLength=-1);
@@ -80,7 +65,10 @@ public:
 	unsigned int BlockSize() const {return BLOCKSIZE;}
 	unsigned int DigestSize() const {return DIGESTSIZE;}
 
+	std::string AlgorithmProvider() const;
+
 protected:
+	// TODO: No longer needed. Remove at next major version bump
 	void HashBlocks(const byte *input, size_t length, word32 padbit);
 	void HashFinal(byte *mac, size_t length);
 
@@ -104,9 +92,13 @@ protected:
 /// \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide
 ///   variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length
 ///   message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce.
-/// \details Each message must use a unique security context, which means either the key or nonce
+/// \details The key is 32 bytes and a concatenation <tt>key = {k,s}</tt>, where
+///   <tt>k</tt> is the AES key and <tt>r</tt> is additional key that gets clamped.
+///   The key is clamped internally so there is no need to perform the operation
+///   before setting the key.
+/// \details Each message must have a unique security context, which means either the key or nonce
 ///   must be changed after each message. It can be accomplished in one of two ways. First, you
-///   can create a new Poly1305 object with a key and nonce each time its needed.
+///   can create a new Poly1305 object each time its needed.
 ///   <pre>  SecByteBlock key(32), nonce(16);
 ///   prng.GenerateBlock(key, key.size());
 ///   prng.GenerateBlock(nonce, nonce.size());
@@ -116,8 +108,7 @@ protected:
 ///   poly1305.Final(...);</pre>
 ///
 /// \details Second, you can create a Poly1305 object, reuse the key, and set a fresh nonce
-///   for each message. The second and subsequent nonces can be generated directly using a
-///   RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
+///   for each message. The second and subsequent nonces can be generated using GetNextIV().
 ///   <pre>  SecByteBlock key(32), nonce(16);
 ///   prng.GenerateBlock(key, key.size());
 ///   prng.GenerateBlock(nonce, nonce.size());
@@ -134,8 +125,9 @@ protected:
 ///   poly1305.Update(...);
 ///   poly1305.Final(...);
 ///   ...</pre>
-/// \warning The Poly1305 class does not enforce a fresh nonce for each message. The source code
-///   will assert in debug builds to alert of nonce reuse. No action is taken in release builds.
+/// \warning Each message must have a unique security context. The Poly1305 class does not
+///   enforce a fresh key or nonce for each message. The source code will assert in debug
+///   builds to alert of nonce reuse. No action is taken in release builds.
 /// \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES
 ///   Message-Authentication Code (20050329)</A> and Andy Polyakov <A
 ///   HREF="http://www.openssl.org/blog/blog/2016/02/15/poly1305-revised/">Poly1305 Revised</A>
@@ -144,7 +136,7 @@ template <class T>
 class Poly1305 : public MessageAuthenticationCodeFinal<Poly1305_Base<T> >
 {
 public:
-	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=Poly1305_Base<T>::DEFAULT_KEYLENGTH)
+	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=Poly1305_Base<T>::DEFAULT_KEYLENGTH);
 
 	/// \brief Construct a Poly1305
 	Poly1305() {}
@@ -154,14 +146,96 @@ public:
 	/// \param keyLength the size of the byte array, in bytes
 	/// \param nonce a byte array used to key the cipher
 	/// \param nonceLength the size of the byte array, in bytes
-	/// \details key is the 32-byte key composed of the 16-byte AES key and the 16 additional key
-	///   bytes used for <tt>r</tt>.
-	/// \details Each message requires a unique security context. You can use GetNextIV() and
-	///   Resynchronize() to set a new nonce under a key for a message.
+	/// \details The key is 32 bytes and a concatenation <tt>key = {k,s}</tt>, where
+	///   <tt>k</tt> is the AES key and <tt>r</tt> is additional key that gets clamped.
+	///   The key is clamped internally so there is no need to perform the operation
+	///   before setting the key.
+	/// \details Each message requires a unique security context. You can use GetNextIV()
+	///   and Resynchronize() to set a new nonce under a key for a message.
 	Poly1305(const byte *key, size_t keyLength=DEFAULT_KEYLENGTH, const byte *nonce=NULLPTR, size_t nonceLength=0)
 		{this->SetKey(key, keyLength, MakeParameters(Name::IV(), ConstByteArrayParameter(nonce, nonceLength)));}
 };
 
+////////////////////////////// IETF Poly1305 //////////////////////////////
+
+/// \brief Poly1305-TLS message authentication code base class
+/// \details Poly1305TLS_Base is the base class of the IETF's Poly1305 algorithm.
+/// \since Crypto++ 8.1
+class Poly1305TLS_Base : public FixedKeyLength<32>, public MessageAuthenticationCode
+{
+public:
+	static std::string StaticAlgorithmName() {return std::string("Poly1305TLS");}
+	CRYPTOPP_CONSTANT(DIGESTSIZE=16);
+	CRYPTOPP_CONSTANT(BLOCKSIZE=16);
+
+	virtual ~Poly1305TLS_Base() {}
+	Poly1305TLS_Base() {}
+
+	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+	void Update(const byte *input, size_t length);
+	void TruncatedFinal(byte *mac, size_t size);
+	void Restart();
+
+	unsigned int BlockSize() const {return BLOCKSIZE;}
+	unsigned int DigestSize() const {return DIGESTSIZE;}
+
+protected:
+	// Accumulated hash, clamped r-key, and encrypted nonce
+	FixedSizeAlignedSecBlock<word32, 5> m_h;
+	FixedSizeAlignedSecBlock<word32, 4> m_r;
+	FixedSizeAlignedSecBlock<word32, 4> m_n;
+
+	// Accumulated message bytes and index
+	FixedSizeAlignedSecBlock<byte, BLOCKSIZE> m_acc;
+	size_t m_idx;
+};
+
+/// \brief Poly1305-TLS message authentication code
+/// \details This is the IETF's variant of Bernstein's Poly1305 from RFC 8439.
+///   IETF Poly1305 is called Poly1305TLS in the Crypto++ library. It is
+///   _slightly_ different from the Bernstein implementation. Poly1305-TLS
+///   can be used for cipher suites
+///   <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
+///   <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and
+///   <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
+/// \details The key is 32 bytes and a concatenation <tt>key = {r,s}</tt>, where
+///   <tt>r</tt> is additional key that gets clamped and <tt>s</tt> is the nonce.
+///   The key is clamped internally so there is no need to perform the operation
+///   before setting the key.
+/// \details Each message must have a unique security context, which means the key
+///   must be changed after each message. It can be accomplished in one of two ways.
+///   First, you can create a new Poly1305 object with a new key each time its needed.
+///   <pre>  SecByteBlock key(32);
+///   prng.GenerateBlock(key, key.size());
+///
+///   Poly1305TLS poly1305(key, key.size());
+///   poly1305.Update(...);
+///   poly1305.Final(...);</pre>
+///
+/// \details Second, you can create a Poly1305 object, and use a new key for each
+///   message. The keys can be generated directly using a RandomNumberGenerator()
+///   derived class.
+///   <pre>  SecByteBlock key(32);
+///   prng.GenerateBlock(key, key.size());
+///
+///   // First message
+///   Poly1305TLS poly1305(key, key.size());
+///   poly1305.Update(...);
+///   poly1305.Final(...);
+///
+///   // Second message
+///   prng.GenerateBlock(key, key.size());
+///   poly1305.SetKey(key, key.size());
+///   poly1305.Update(...);
+///   poly1305.Final(...);
+///   ...</pre>
+/// \warning Each message must have a unique security context. The Poly1305-TLS class
+///   does not enforce a fresh key or nonce for each message.
+/// \since Crypto++ 8.1
+/// \sa MessageAuthenticationCode(), <a href="http://tools.ietf.org/html/rfc8439">RFC
+///   8439, ChaCha20 and Poly1305 for IETF Protocols</a>
+DOCUMENTED_TYPEDEF(MessageAuthenticationCodeFinal<Poly1305TLS_Base>, Poly1305TLS);
+
 NAMESPACE_END
 
 #endif  // CRYPTOPP_POLY1305_H

+ 2764 - 0
include/cryptlib/ppc_simd.h

@@ -0,0 +1,2764 @@
+// ppc_simd.h - written and placed in public domain by Jeffrey Walton
+
+/// \file ppc_simd.h
+/// \brief Support functions for PowerPC and vector operations
+/// \details This header provides an agnostic interface into Clang, GCC
+///  and IBM XL C/C++ compilers modulo their different built-in functions
+///  for accessing vector instructions.
+/// \details The abstractions are necessary to support back to GCC 4.8 and
+///  XLC 11 and 12. GCC 4.8 and 4.9 are still popular, and they are the
+///  default compiler for GCC112, GCC119 and others on the compile farm.
+///  Older IBM XL C/C++ compilers also have the need due to lack of
+///  <tt>vec_xl</tt> and <tt>vec_xst</tt> support on some platforms. Modern
+///  compilers provide best support and don't need many of the hacks
+///  below.
+/// \details The library is tested with the following PowerPC machines and
+///  compilers. GCC110, GCC111, GCC112, GCC119 and GCC135 are provided by
+///  the <A HREF="https://cfarm.tetaneutral.net/">GCC Compile Farm</A>
+///  - PowerMac G5, OSX 10.5, POWER4, Apple GCC 4.0
+///  - PowerMac G5, OSX 10.5, POWER4, Macports GCC 5.0
+///  - GCC110, Linux, POWER7, GCC 4.8.5
+///  - GCC110, Linux, POWER7, XLC 12.01
+///  - GCC111, AIX, POWER7, GCC 4.8.1
+///  - GCC111, AIX, POWER7, XLC 12.01
+///  - GCC112, Linux, POWER8, GCC 4.8.5
+///  - GCC112, Linux, POWER8, XLC 13.01
+///  - GCC112, Linux, POWER8, Clang 7.0
+///  - GCC119, AIX, POWER8, GCC 7.2.0
+///  - GCC119, AIX, POWER8, XLC 13.01
+///  - GCC135, Linux, POWER9, GCC 7.0
+/// \details 12 machines are used for testing because the three compilers form
+///  five or six profiles. The profiles are listed below.
+///  - GCC (Linux GCC, Macports GCC, etc. Consistent across machines)
+///  - XLC 13.0 and earlier (all IBM components)
+///  - XLC 13.1 and later on Linux (LLVM front-end, no compatibility macros)
+///  - XLC 13.1 and later on Linux (LLVM front-end, -qxlcompatmacros option)
+///  - early LLVM Clang (traditional Clang compiler)
+///  - late LLVM Clang (traditional Clang compiler)
+/// \details The LLVM front-end makes it tricky to write portable code because
+///  LLVM pretends to be other compilers but cannot consume other compiler's
+///  builtins. When using XLC with -qxlcompatmacros the compiler pretends to
+///  be GCC, Clang and XLC all at once but it can only consume it's variety
+///  of builtins.
+/// \details At Crypto++ 8.0 the various <tt>Vector{FuncName}</tt> were
+///  renamed to <tt>Vec{FuncName}</tt>. For example, <tt>VectorAnd</tt> was
+///  changed to <tt>VecAnd</tt>. The name change helped consolidate two
+///  slightly different implementations.
+/// \details At Crypto++ 8.3 the library added select 64-bit functions for
+///  32-bit Altivec. For example, <tt>VecAdd64</tt> and <tt>VecSub64</tt>
+///  take 32-bit vectors and adds or subtracts them as if there were vectors
+///  with two 64-bit elements. The functions dramtically improve performance
+///  for some algorithms on some platforms, like SIMON128 and SPECK128 on
+///  Power6 and earlier. For example, SPECK128 improved from 70 cpb to
+///  10 cpb on an old PowerMac. Use the functions like shown below.
+///  <pre>
+///    \#if defined(_ARCH_PWR8)
+///    \#  define speck128_t uint64x2_p
+///    \#else
+///    \#  define speck128_t uint32x4_p
+///    \#endif
+///
+///    speck128_t rk, x1, x2, y1, y2;
+///    rk = (speck128_t)VecLoadAligned(ptr);
+///    x1 = VecRotateRight64<8>(x1);
+///    x1 = VecAdd64(x1, y1);
+///    ...</pre>
+/// \since Crypto++ 6.0, LLVM Clang compiler support since Crypto++ 8.0
+
+// Use __ALTIVEC__, _ARCH_PWR7, __VSX__, and _ARCH_PWR8 when detecting
+// actual availaibility of the feature for the source file being compiled.
+// The preprocessor macros depend on compiler options like -maltivec; and
+// not compiler versions.
+
+// For GCC see https://gcc.gnu.org/onlinedocs/gcc/Basic-PowerPC-Built-in-Functions.html
+// For XLC see the Compiler Reference manual. For Clang you have to experiment.
+// Clang does not document the compiler options, does not reject options it does
+// not understand, and pretends to be other compilers even though it cannot
+// process the builtins and intrinsics. Clang will waste hours of your time.
+
+// DO NOT USE this pattern in VecLoad and VecStore. We have to use the
+// code paths guarded by preprocessor macros because XLC 12 generates
+// bad code in some places. To verify the bad code generation test on
+// GCC111 with XLC 12.01 installed. XLC 13.01 on GCC112 and GCC119 are OK.
+//
+//   inline uint32x4_p VecLoad(const byte src[16])
+//   {
+//   #if defined(__VSX__) || defined(_ARCH_PWR8)
+//       return (uint32x4_p) *(uint8x16_p*)((byte*)src);
+//   #else
+//       return VecLoad_ALTIVEC(src);
+//   #endif
+//   }
+
+// We should be able to perform the load using inline asm on Power7 with
+// VSX or Power8. The inline asm will avoid C undefined behavior due to
+// casting from byte* to word32*. We are safe because our byte* are
+// 16-byte aligned for Altivec. Below is the big endian load. Little
+// endian would need to follow with xxpermdi for the reversal.
+//
+//   __asm__ ("lxvw4x %x0, %1, %2" : "=wa"(v) : "r"(0), "r"(src) : );
+
+// GCC and XLC use integer math for the address (D-form or byte-offset
+// in the ISA manual). LLVM uses pointer math for the address (DS-form
+// or indexed in the ISA manual). To keep them consistent we calculate
+// the address from the offset and pass to a load or store function
+// using a 0 offset.
+
+#ifndef CRYPTOPP_PPC_CRYPTO_H
+#define CRYPTOPP_PPC_CRYPTO_H
+
+#include "config.h"
+#include "misc.h"
+
+#if defined(__ALTIVEC__)
+# include <altivec.h>
+# undef vector
+# undef pixel
+# undef bool
+#endif
+
+// XL C++ on AIX does not define VSX and does not
+// provide an option to set it. We have to set it
+// for the code below. This define must stay in
+// sync with the define in test_ppc_power7.cpp.
+#ifndef CRYPTOPP_DISABLE_POWER7
+# if defined(_AIX) && defined(_ARCH_PWR7) && defined(__xlC__)
+#  define __VSX__ 1
+# endif
+#endif
+
+// XL C++ on AIX does not define CRYPTO and does not
+// provide an option to set it. We have to set it
+// for the code below. This define must stay in
+// sync with the define in test_ppc_power8.cpp
+#ifndef CRYPTOPP_DISABLE_POWER8
+# if defined(_AIX) && defined(_ARCH_PWR8) && defined(__xlC__)
+#  define __CRYPTO__ 1
+# endif
+#endif
+
+/// \brief Cast array to vector pointer
+/// \details CONST_V8_CAST casts a const array to a vector
+///  pointer for a byte array. The Power ABI says source arrays
+///  are non-const, so this define removes the const. XLC++ will
+///  fail the compile if the source array is const.
+#define CONST_V8_CAST(x)  ((unsigned char*)(x))
+/// \brief Cast array to vector pointer
+/// \details CONST_V32_CAST casts a const array to a vector
+///  pointer for a word array. The Power ABI says source arrays
+///  are non-const, so this define removes the const. XLC++ will
+///  fail the compile if the source array is const.
+#define CONST_V32_CAST(x) ((unsigned int*)(x))
+/// \brief Cast array to vector pointer
+/// \details CONST_V64_CAST casts a const array to a vector
+///  pointer for a double word array. The Power ABI says source arrays
+///  are non-const, so this define removes the const. XLC++ will
+///  fail the compile if the source array is const.
+#define CONST_V64_CAST(x) ((unsigned long long*)(x))
+/// \brief Cast array to vector pointer
+/// \details NCONST_V8_CAST casts an array to a vector
+///  pointer for a byte array. The Power ABI says source arrays
+///  are non-const, so this define removes the const. XLC++ will
+///  fail the compile if the source array is const.
+#define NCONST_V8_CAST(x)  ((unsigned char*)(x))
+/// \brief Cast array to vector pointer
+/// \details NCONST_V32_CAST casts an array to a vector
+///  pointer for a word array. The Power ABI says source arrays
+///  are non-const, so this define removes the const. XLC++ will
+///  fail the compile if the source array is const.
+#define NCONST_V32_CAST(x) ((unsigned int*)(x))
+/// \brief Cast array to vector pointer
+/// \details NCONST_V64_CAST casts an array to a vector
+///  pointer for a double word array. The Power ABI says source arrays
+///  are non-const, so this define removes the const. XLC++ will
+///  fail the compile if the source array is const.
+#define NCONST_V64_CAST(x) ((unsigned long long*)(x))
+
+// VecLoad_ALTIVEC and VecStore_ALTIVEC are
+// too noisy on modern compilers
+#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if defined(__ALTIVEC__) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+/// \brief Vector of 8-bit elements
+/// \par Wraps
+///  __vector unsigned char
+/// \since Crypto++ 6.0
+typedef __vector unsigned char   uint8x16_p;
+/// \brief Vector of 16-bit elements
+/// \par Wraps
+///  __vector unsigned short
+/// \since Crypto++ 6.0
+typedef __vector unsigned short  uint16x8_p;
+/// \brief Vector of 32-bit elements
+/// \par Wraps
+///  __vector unsigned int
+/// \since Crypto++ 6.0
+typedef __vector unsigned int    uint32x4_p;
+
+#if defined(__VSX__) || defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Vector of 64-bit elements
+/// \details uint64x2_p is available on POWER7 with VSX and above. Most
+///  supporting functions, like 64-bit <tt>vec_add</tt> (<tt>vaddudm</tt>)
+///  and <tt>vec_sub</tt> (<tt>vsubudm</tt>), did not arrive until POWER8.
+/// \par Wraps
+///  __vector unsigned long long
+/// \since Crypto++ 6.0
+typedef __vector unsigned long long uint64x2_p;
+#endif  // VSX or ARCH_PWR8
+
+/// \brief The 0 vector
+/// \return a 32-bit vector of 0's
+/// \since Crypto++ 8.0
+inline uint32x4_p VecZero()
+{
+    const uint32x4_p v = {0,0,0,0};
+    return v;
+}
+
+/// \brief The 1 vector
+/// \return a 32-bit vector of 1's
+/// \since Crypto++ 8.0
+inline uint32x4_p VecOne()
+{
+    const uint32x4_p v = {1,1,1,1};
+    return v;
+}
+
+/// \brief Reverse bytes in a vector
+/// \tparam T vector type
+/// \param data the vector
+/// \return vector
+/// \details VecReverse() reverses the bytes in a vector
+/// \par Wraps
+///  vec_perm
+/// \since Crypto++ 6.0
+template <class T>
+inline T VecReverse(const T data)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    const uint8x16_p mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0};
+    return (T)vec_perm(data, data, mask);
+#else
+    const uint8x16_p mask = {0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15};
+    return (T)vec_perm(data, data, mask);
+#endif
+}
+
+/// \brief Reverse bytes in a vector
+/// \tparam T vector type
+/// \param data the vector
+/// \return vector
+/// \details VecReverseLE() reverses the bytes in a vector on
+///  little-endian systems.
+/// \par Wraps
+///  vec_perm
+/// \since Crypto++ 6.0
+template <class T>
+inline T VecReverseLE(const T data)
+{
+#if defined(CRYPTOPP_LITTLE_ENDIAN)
+    const uint8x16_p mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0};
+    return (T)vec_perm(data, data, mask);
+#else
+    return data;
+#endif
+}
+
+/// \brief Reverse bytes in a vector
+/// \tparam T vector type
+/// \param data the vector
+/// \return vector
+/// \details VecReverseBE() reverses the bytes in a vector on
+///  big-endian systems.
+/// \par Wraps
+///  vec_perm
+/// \since Crypto++ 6.0
+template <class T>
+inline T VecReverseBE(const T data)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    const uint8x16_p mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0};
+    return (T)vec_perm(data, data, mask);
+#else
+    return data;
+#endif
+}
+
+/// \name LOAD OPERATIONS
+//@{
+
+/// \brief Loads a vector from a byte array
+/// \param src the byte array
+/// \details Loads a vector in native endian format from a byte array.
+/// \details VecLoad_ALTIVEC() uses <tt>vec_ld</tt> if the effective address
+///  of <tt>src</tt> is aligned. If unaligned it uses <tt>vec_lvsl</tt>,
+///  <tt>vec_ld</tt>, <tt>vec_perm</tt> and <tt>src</tt>. The fixups using
+///  <tt>vec_lvsl</tt> and <tt>vec_perm</tt> are relatively expensive so
+///  you should provide aligned memory addresses.
+/// \par Wraps
+///  vec_ld, vec_lvsl, vec_perm
+/// \sa VecLoad, VecLoadAligned
+/// \since Crypto++ 6.0
+inline uint32x4_p VecLoad_ALTIVEC(const byte src[16])
+{
+    // Avoid IsAlignedOn for convenience.
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    if (addr % 16 == 0)
+    {
+        return (uint32x4_p)vec_ld(0, CONST_V8_CAST(addr));
+    }
+    else
+    {
+        // http://www.nxp.com/docs/en/reference-manual/ALTIVECPEM.pdf
+        const uint8x16_p perm = vec_lvsl(0, CONST_V8_CAST(addr));
+        const uint8x16_p low = vec_ld(0, CONST_V8_CAST(addr));
+        const uint8x16_p high = vec_ld(15, CONST_V8_CAST(addr));
+        return (uint32x4_p)vec_perm(low, high, perm);
+    }
+}
+
+/// \brief Loads a vector from a byte array
+/// \param src the byte array
+/// \param off offset into the src byte array
+/// \details Loads a vector in native endian format from a byte array.
+/// \details VecLoad_ALTIVEC() uses <tt>vec_ld</tt> if the effective address
+///  of <tt>src</tt> is aligned. If unaligned it uses <tt>vec_lvsl</tt>,
+///  <tt>vec_ld</tt>, <tt>vec_perm</tt> and <tt>src</tt>.
+/// \details The fixups using <tt>vec_lvsl</tt> and <tt>vec_perm</tt> are
+///  relatively expensive so you should provide aligned memory addresses.
+/// \par Wraps
+///  vec_ld, vec_lvsl, vec_perm
+/// \sa VecLoad, VecLoadAligned
+/// \since Crypto++ 6.0
+inline uint32x4_p VecLoad_ALTIVEC(int off, const byte src[16])
+{
+    // Avoid IsAlignedOn for convenience.
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    if (addr % 16 == 0)
+    {
+        return (uint32x4_p)vec_ld(0, CONST_V8_CAST(addr));
+    }
+    else
+    {
+        // http://www.nxp.com/docs/en/reference-manual/ALTIVECPEM.pdf
+        const uint8x16_p perm = vec_lvsl(0, CONST_V8_CAST(addr));
+        const uint8x16_p low = vec_ld(0, CONST_V8_CAST(addr));
+        const uint8x16_p high = vec_ld(15, CONST_V8_CAST(addr));
+        return (uint32x4_p)vec_perm(low, high, perm);
+    }
+}
+
+/// \brief Loads a vector from a byte array
+/// \param src the byte array
+/// \details VecLoad() loads a vector from a byte array.
+/// \details VecLoad() uses POWER9's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER9 is not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xl on POWER9 and above, Altivec load on POWER8 and below
+/// \sa VecLoad_ALTIVEC, VecLoadAligned
+/// \since Crypto++ 6.0
+inline uint32x4_p VecLoad(const byte src[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(0, CONST_V8_CAST(src));
+#else
+    return (uint32x4_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Loads a vector from a byte array
+/// \param src the byte array
+/// \param off offset into the src byte array
+/// \details VecLoad() loads a vector from a byte array.
+/// \details VecLoad() uses POWER9's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER9 is not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xl on POWER9 and above, Altivec load on POWER8 and below
+/// \sa VecLoad_ALTIVEC, VecLoadAligned
+/// \since Crypto++ 6.0
+inline uint32x4_p VecLoad(int off, const byte src[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(off, CONST_V8_CAST(src));
+#else
+    return (uint32x4_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Loads a vector from a word array
+/// \param src the word array
+/// \details VecLoad() loads a vector from a word array.
+/// \details VecLoad() uses POWER7's and VSX's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER7 is not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, Altivec load on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoadAligned
+/// \since Crypto++ 8.0
+inline uint32x4_p VecLoad(const word32 src[4])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(0, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    return (uint32x4_p)vec_xl(0, CONST_V32_CAST(addr));
+#else
+    return (uint32x4_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Loads a vector from a word array
+/// \param src the word array
+/// \param off offset into the word array
+/// \details VecLoad() loads a vector from a word array.
+/// \details VecLoad() uses POWER7's and VSX's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER7 is not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, Altivec load on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoadAligned
+/// \since Crypto++ 8.0
+inline uint32x4_p VecLoad(int off, const word32 src[4])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(off, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    return (uint32x4_p)vec_xl(0, CONST_V32_CAST(addr));
+#else
+    return (uint32x4_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#endif
+}
+
+#if defined(__VSX__) || defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+/// \brief Loads a vector from a double word array
+/// \param src the double word array
+/// \details VecLoad() loads a vector from a double word array.
+/// \details VecLoad() uses POWER7's and VSX's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER7 and VSX are not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \details VecLoad() with 64-bit elements is available on POWER7 and above.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, Altivec load on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoadAligned
+/// \since Crypto++ 8.0
+inline uint64x2_p VecLoad(const word64 src[2])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word64>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint64x2_p)vec_xl(0, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    // The 32-bit cast is not a typo. Compiler workaround.
+    return (uint64x2_p)vec_xl(0, CONST_V32_CAST(addr));
+#else
+    return (uint64x2_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Loads a vector from a double word array
+/// \param src the double word array
+/// \param off offset into the double word array
+/// \details VecLoad() loads a vector from a double word array.
+/// \details VecLoad() uses POWER7's and VSX's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER7 and VSX are not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \details VecLoad() with 64-bit elements is available on POWER8 and above.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, Altivec load on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoadAligned
+/// \since Crypto++ 8.0
+inline uint64x2_p VecLoad(int off, const word64 src[2])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word64>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint64x2_p)vec_xl(off, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    // The 32-bit cast is not a typo. Compiler workaround.
+    return (uint64x2_p)vec_xl(0, CONST_V32_CAST(addr));
+#else
+    return (uint64x2_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#endif
+}
+
+#endif  // VSX or ARCH_PWR8
+
+/// \brief Loads a vector from an aligned byte array
+/// \param src the byte array
+/// \details VecLoadAligned() loads a vector from an aligned byte array.
+/// \details VecLoadAligned() uses POWER9's <tt>vec_xl</tt> if available.
+///  <tt>vec_ld</tt> is used if POWER9 is not available. The effective
+///  address of <tt>src</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xl on POWER9, vec_ld on POWER8 and below
+/// \sa VecLoad_ALTIVEC, VecLoad
+/// \since Crypto++ 8.0
+inline uint32x4_p VecLoadAligned(const byte src[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    CRYPTOPP_ASSERT(addr % 16 == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(0, CONST_V8_CAST(src));
+#else
+    return (uint32x4_p)vec_ld(0, CONST_V8_CAST(src));
+#endif
+}
+
+/// \brief Loads a vector from an aligned byte array
+/// \param src the byte array
+/// \param off offset into the src byte array
+/// \details VecLoadAligned() loads a vector from an aligned byte array.
+/// \details VecLoadAligned() uses POWER9's <tt>vec_xl</tt> if available.
+///  <tt>vec_ld</tt> is used if POWER9 is not available. The effective
+///  address of <tt>src</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xl on POWER9, vec_ld on POWER8 and below
+/// \sa VecLoad_ALTIVEC, VecLoad
+/// \since Crypto++ 8.0
+inline uint32x4_p VecLoadAligned(int off, const byte src[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    CRYPTOPP_ASSERT(addr % 16 == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(off, CONST_V8_CAST(src));
+#else
+    return (uint32x4_p)vec_ld(off, CONST_V8_CAST(src));
+#endif
+}
+
+/// \brief Loads a vector from an aligned word array
+/// \param src the word array
+/// \details VecLoadAligned() loads a vector from an aligned word array.
+/// \details VecLoadAligned() uses POWER7's and VSX's <tt>vec_xl</tt> if
+///  available. <tt>vec_ld</tt> is used if POWER7 or VSX are not available.
+///  The effective address of <tt>src</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, vec_ld on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoad
+/// \since Crypto++ 8.0
+inline uint32x4_p VecLoadAligned(const word32 src[4])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    CRYPTOPP_ASSERT(addr % 16 == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(0, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    return (uint32x4_p)vec_xl(0, CONST_V32_CAST(src));
+#else
+    return (uint32x4_p)vec_ld(0, CONST_V8_CAST(src));
+#endif
+}
+
+/// \brief Loads a vector from an aligned word array
+/// \param src the word array
+/// \param off offset into the src word array
+/// \details VecLoadAligned() loads a vector from an aligned word array.
+/// \details VecLoadAligned() uses POWER7's and VSX's <tt>vec_xl</tt> if
+///  available. <tt>vec_ld</tt> is used if POWER7 or VSX are not available.
+///  The effective address of <tt>src</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, vec_ld on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoad
+/// \since Crypto++ 8.0
+inline uint32x4_p VecLoadAligned(int off, const word32 src[4])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    CRYPTOPP_ASSERT(addr % 16 == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint32x4_p)vec_xl(off, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    return (uint32x4_p)vec_xl(0, CONST_V32_CAST(addr));
+#else
+    return (uint32x4_p)vec_ld(off, CONST_V8_CAST(src));
+#endif
+}
+
+#if defined(__VSX__) || defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+/// \brief Loads a vector from an aligned double word array
+/// \param src the double word array
+/// \details VecLoadAligned() loads a vector from an aligned double word array.
+/// \details VecLoadAligned() uses POWER7's and VSX's <tt>vec_xl</tt> if
+///  available. <tt>vec_ld</tt> is used if POWER7 or VSX are not available.
+///  The effective address of <tt>src</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, vec_ld on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoad
+/// \since Crypto++ 8.0
+inline uint64x2_p VecLoadAligned(const word64 src[4])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    CRYPTOPP_ASSERT(addr % 16 == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint64x2_p)vec_xl(0, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    // The 32-bit cast is not a typo. Compiler workaround.
+    return (uint64x2_p)vec_xl(0, CONST_V32_CAST(src));
+#else
+    return (uint64x2_p)vec_ld(0, CONST_V8_CAST(src));
+#endif
+}
+
+/// \brief Loads a vector from an aligned double word array
+/// \param src the double word array
+/// \param off offset into the src double word array
+/// \details VecLoadAligned() loads a vector from an aligned double word array.
+/// \details VecLoadAligned() uses POWER7's and VSX's <tt>vec_xl</tt> if
+///  available. <tt>vec_ld</tt> is used if POWER7 or VSX are not available.
+///  The effective address of <tt>src</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xl on VSX or POWER8 and above, vec_ld on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoad
+/// \since Crypto++ 8.0
+inline uint64x2_p VecLoadAligned(int off, const word64 src[4])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    CRYPTOPP_ASSERT(addr % 16 == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    return (uint64x2_p)vec_xl(off, CONST_V8_CAST(src));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    // The 32-bit cast is not a typo. Compiler workaround.
+    return (uint64x2_p)vec_xl(0, CONST_V32_CAST(addr));
+#else
+    return (uint64x2_p)vec_ld(off, CONST_V8_CAST(src));
+#endif
+}
+
+#endif
+
+/// \brief Loads a vector from a byte array
+/// \param src the byte array
+/// \details VecLoadBE() loads a vector from a byte array. VecLoadBE
+///  will reverse all bytes in the array on a little endian system.
+/// \details VecLoadBE() uses POWER7's and VSX's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER7 or VSX are not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xl on POWER8, Altivec load on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoad, VecLoadAligned
+/// \since Crypto++ 6.0
+inline uint32x4_p VecLoadBE(const byte src[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src);
+    // CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    return (uint32x4_p)vec_xl_be(0, CONST_V8_CAST(src));
+#elif defined(CRYPTOPP_BIG_ENDIAN)
+    return (uint32x4_p)VecLoad_ALTIVEC(0, CONST_V8_CAST(src));
+#else
+    return (uint32x4_p)VecReverseLE(VecLoad_ALTIVEC(CONST_V8_CAST(src)));
+#endif
+}
+
+/// \brief Loads a vector from a byte array
+/// \param src the byte array
+/// \param off offset into the src byte array
+/// \details VecLoadBE() loads a vector from a byte array. VecLoadBE
+///  will reverse all bytes in the array on a little endian system.
+/// \details VecLoadBE() uses POWER7's and VSX's <tt>vec_xl</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecLoad_ALTIVEC() is used if POWER7 is not available.
+///  VecLoad_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xl on POWER8, Altivec load on POWER7 and below
+/// \sa VecLoad_ALTIVEC, VecLoad, VecLoadAligned
+/// \since Crypto++ 6.0
+inline uint32x4_p VecLoadBE(int off, const byte src[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(src)+off;
+    // CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    return (uint32x4_p)vec_xl_be(off, CONST_V8_CAST(src));
+#elif defined(CRYPTOPP_BIG_ENDIAN)
+    return (uint32x4_p)VecLoad_ALTIVEC(CONST_V8_CAST(addr));
+#else
+    return (uint32x4_p)VecReverseLE(VecLoad_ALTIVEC(CONST_V8_CAST(addr)));
+#endif
+}
+
+//@}
+
+/// \name STORE OPERATIONS
+//@{
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the byte array
+/// \details VecStore_ALTIVEC() stores a vector to a byte array.
+/// \details VecStore_ALTIVEC() uses <tt>vec_st</tt> if the effective address
+///  of <tt>dest</tt> is aligned, and uses <tt>vec_ste</tt> otherwise.
+///  <tt>vec_ste</tt> is relatively expensive so you should provide aligned
+///  memory addresses.
+/// \details VecStore_ALTIVEC() is used when POWER7 or above
+///  and unaligned loads is not available.
+/// \par Wraps
+///  vec_st, vec_ste, vec_lvsr, vec_perm
+/// \sa VecStore, VecStoreAligned
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStore_ALTIVEC(const T data, byte dest[16])
+{
+    // Avoid IsAlignedOn for convenience.
+    uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    if (addr % 16 == 0)
+    {
+        vec_st((uint8x16_p)data, 0, NCONST_V8_CAST(addr));
+    }
+    else
+    {
+        // http://www.nxp.com/docs/en/reference-manual/ALTIVECPEM.pdf
+        uint8x16_p perm = (uint8x16_p)vec_perm(data, data, vec_lvsr(0, NCONST_V8_CAST(addr)));
+        vec_ste((uint8x16_p) perm,  0, (unsigned char*) NCONST_V8_CAST(addr));
+        vec_ste((uint16x8_p) perm,  1, (unsigned short*)NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm,  3, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm,  4, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm,  8, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm, 12, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint16x8_p) perm, 14, (unsigned short*)NCONST_V8_CAST(addr));
+        vec_ste((uint8x16_p) perm, 15, (unsigned char*) NCONST_V8_CAST(addr));
+    }
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest byte array
+/// \param dest the byte array
+/// \details VecStore_ALTIVEC() stores a vector to a byte array.
+/// \details VecStore_ALTIVEC() uses <tt>vec_st</tt> if the effective address
+///  of <tt>dest</tt> is aligned, and uses <tt>vec_ste</tt> otherwise.
+///  <tt>vec_ste</tt> is relatively expensive so you should provide aligned
+///  memory addresses.
+/// \details VecStore_ALTIVEC() is used when POWER7 or above
+///  and unaligned loads is not available.
+/// \par Wraps
+///  vec_st, vec_ste, vec_lvsr, vec_perm
+/// \sa VecStore, VecStoreAligned
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStore_ALTIVEC(const T data, int off, byte dest[16])
+{
+    // Avoid IsAlignedOn for convenience.
+    uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    if (addr % 16 == 0)
+    {
+        vec_st((uint8x16_p)data, 0, NCONST_V8_CAST(addr));
+    }
+    else
+    {
+        // http://www.nxp.com/docs/en/reference-manual/ALTIVECPEM.pdf
+        uint8x16_p perm = (uint8x16_p)vec_perm(data, data, vec_lvsr(0, NCONST_V8_CAST(addr)));
+        vec_ste((uint8x16_p) perm,  0, (unsigned char*) NCONST_V8_CAST(addr));
+        vec_ste((uint16x8_p) perm,  1, (unsigned short*)NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm,  3, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm,  4, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm,  8, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint32x4_p) perm, 12, (unsigned int*)  NCONST_V8_CAST(addr));
+        vec_ste((uint16x8_p) perm, 14, (unsigned short*)NCONST_V8_CAST(addr));
+        vec_ste((uint8x16_p) perm, 15, (unsigned char*) NCONST_V8_CAST(addr));
+    }
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the byte array
+/// \details VecStore() stores a vector to a byte array.
+/// \details VecStore() uses POWER9's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER9 is not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on POWER9 and above, Altivec store on POWER8 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 6.0
+template<class T>
+inline void VecStore(const T data, byte dest[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#else
+    VecStore_ALTIVEC((uint8x16_p)data, NCONST_V8_CAST(dest));
+#endif
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest byte array
+/// \param dest the byte array
+/// \details VecStore() stores a vector to a byte array.
+/// \details VecStore() uses POWER9's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER9 is not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on POWER9 and above, Altivec store on POWER8 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 6.0
+template<class T>
+inline void VecStore(const T data, int off, byte dest[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#else
+    VecStore_ALTIVEC((uint8x16_p)data, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the word array
+/// \details VecStore() stores a vector to a word array.
+/// \details VecStore() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 or VSX are not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, Altivec store on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStore(const T data, word32 dest[4])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    vec_xst((uint32x4_p)data, 0, NCONST_V32_CAST(addr));
+#else
+    VecStore_ALTIVEC((uint8x16_p)data, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest word array
+/// \param dest the word array
+/// \details VecStore() stores a vector to a word array.
+/// \details VecStore() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 or VSX are not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, Altivec store on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStore(const T data, int off, word32 dest[4])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    vec_xst((uint32x4_p)data, 0, NCONST_V32_CAST(addr));
+#else
+    VecStore_ALTIVEC((uint8x16_p)data, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the word array
+/// \details VecStore() stores a vector to a word array.
+/// \details VecStore() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 or VSX are not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \details VecStore() with 64-bit elements is available on POWER8 and above.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, Altivec store on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStore(const T data, word64 dest[2])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word64>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    // 32-bit cast is not a typo. Compiler workaround.
+    vec_xst((uint32x4_p)data, 0, NCONST_V32_CAST(addr));
+#else
+    VecStore_ALTIVEC((uint8x16_p)data, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest word array
+/// \param dest the word array
+/// \details VecStore() stores a vector to a word array.
+/// \details VecStore() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 or VSX are not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \details VecStore() with 64-bit elements is available on POWER8 and above.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, Altivec store on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStore(const T data, int off, word64 dest[2])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word64>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    // 32-bit cast is not a typo. Compiler workaround.
+    vec_xst((uint32x4_p)data, 0, NCONST_V32_CAST(addr));
+#else
+    VecStore_ALTIVEC((uint8x16_p)data, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the byte array
+/// \details VecStoreAligned() stores a vector from an aligned byte array.
+/// \details VecStoreAligned() uses POWER9's <tt>vec_xl</tt> if available.
+///  <tt>vec_st</tt> is used if POWER9 is not available. The effective
+///  address of <tt>dest</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xst on POWER9 or above, vec_st on POWER8 and below
+/// \sa VecStore_ALTIVEC, VecStore
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStoreAligned(const T data, byte dest[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#else
+    vec_st((uint8x16_p)data, 0, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest byte array
+/// \param dest the byte array
+/// \details VecStoreAligned() stores a vector from an aligned byte array.
+/// \details VecStoreAligned() uses POWER9's <tt>vec_xl</tt> if available.
+///  <tt>vec_st</tt> is used if POWER9 is not available. The effective
+///  address of <tt>dest</tt> must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xst on POWER9 or above, vec_st on POWER8 and below
+/// \sa VecStore_ALTIVEC, VecStore
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStoreAligned(const T data, int off, byte dest[16])
+{
+    // Power7/ISA 2.06 provides vec_xl, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks loads for short* and char*.
+    // Power9/ISA 3.0 provides vec_xl for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#else
+    vec_st((uint8x16_p)data, 0, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the word array
+/// \details VecStoreAligned() stores a vector from an aligned word array.
+/// \details VecStoreAligned() uses POWER9's <tt>vec_xl</tt> if available.
+///  POWER7 <tt>vec_xst</tt> is used if POWER9 is not available. <tt>vec_st</tt>
+///  is used if POWER7 is not available. The effective address of <tt>dest</tt>
+///  must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, vec_st on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStore
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStoreAligned(const T data, word32 dest[4])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    vec_xst((uint32x4_p)data, 0, NCONST_V32_CAST(addr));
+#else
+    vec_st((uint8x16_p)data, 0, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest word array
+/// \param dest the word array
+/// \details VecStoreAligned() stores a vector from an aligned word array.
+/// \details VecStoreAligned() uses POWER9's <tt>vec_xl</tt> if available.
+///  POWER7 <tt>vec_xst</tt> is used if POWER9 is not available. <tt>vec_st</tt>
+///  is used if POWER7 is not available. The effective address of <tt>dest</tt>
+///  must be 16-byte aligned for Altivec.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, vec_st on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStore
+/// \since Crypto++ 8.0
+template<class T>
+inline void VecStoreAligned(const T data, int off, word32 dest[4])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#elif defined(__VSX__) || defined(_ARCH_PWR8)
+    vec_xst((uint32x4_p)data, 0, NCONST_V32_CAST(addr));
+#else
+    vec_st((uint8x16_p)data, 0, NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the byte array
+/// \details VecStoreBE() stores a vector to a byte array. VecStoreBE
+///  will reverse all bytes in the array on a little endian system.
+/// \details VecStoreBE() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 is not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, vec_st on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 6.0
+template <class T>
+inline void VecStoreBE(const T data, byte dest[16])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst_be((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#elif defined(CRYPTOPP_BIG_ENDIAN)
+    VecStore((uint8x16_p)data, NCONST_V8_CAST(addr));
+#else
+    VecStore((uint8x16_p)VecReverseLE(data), NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a byte array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest byte array
+/// \param dest the byte array
+/// \details VecStoreBE() stores a vector to a byte array. VecStoreBE
+///  will reverse all bytes in the array on a little endian system.
+/// \details VecStoreBE() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 is not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, vec_st on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 6.0
+template <class T>
+inline void VecStoreBE(const T data, int off, byte dest[16])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<byte>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst_be((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#elif defined(CRYPTOPP_BIG_ENDIAN)
+    VecStore((uint8x16_p)data, NCONST_V8_CAST(addr));
+#else
+    VecStore((uint8x16_p)VecReverseLE(data), NCONST_V8_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param dest the word array
+/// \details VecStoreBE() stores a vector to a word array. VecStoreBE
+///  will reverse all bytes in the array on a little endian system.
+/// \details VecStoreBE() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 is not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, vec_st on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 8.0
+template <class T>
+inline void VecStoreBE(const T data, word32 dest[4])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest);
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst_be((uint8x16_p)data, 0, NCONST_V8_CAST(dest));
+#elif defined(CRYPTOPP_BIG_ENDIAN)
+    VecStore((uint32x4_p)data, NCONST_V32_CAST(addr));
+#else
+    VecStore((uint32x4_p)VecReverseLE(data), NCONST_V32_CAST(addr));
+#endif
+}
+
+/// \brief Stores a vector to a word array
+/// \tparam T vector type
+/// \param data the vector
+/// \param off offset into the dest word array
+/// \param dest the word array
+/// \details VecStoreBE() stores a vector to a word array. VecStoreBE
+///  will reverse all words in the array on a little endian system.
+/// \details VecStoreBE() uses POWER7's and VSX's <tt>vec_xst</tt> if available.
+///  The instruction does not require aligned effective memory addresses.
+///  VecStore_ALTIVEC() is used if POWER7 is not available.
+///  VecStore_ALTIVEC() can be relatively expensive if extra instructions
+///  are required to fix up unaligned memory addresses.
+/// \par Wraps
+///  vec_xst on VSX or POWER8 and above, vec_st on POWER7 and below
+/// \sa VecStore_ALTIVEC, VecStoreAligned
+/// \since Crypto++ 8.0
+template <class T>
+inline void VecStoreBE(const T data, int off, word32 dest[4])
+{
+    // Power7/ISA 2.06 provides vec_xst, but only for 32-bit and 64-bit
+    // word pointers. The ISA lacks stores for short* and char*.
+    // Power9/ISA 3.0 provides vec_xst for all datatypes.
+
+    const uintptr_t addr = reinterpret_cast<uintptr_t>(dest)+off;
+    CRYPTOPP_ASSERT(addr % GetAlignmentOf<word32>() == 0);
+    CRYPTOPP_UNUSED(addr);
+
+#if defined(_ARCH_PWR9)
+    vec_xst_be((uint8x16_p)data, off, NCONST_V8_CAST(dest));
+#elif defined(CRYPTOPP_BIG_ENDIAN)
+    VecStore((uint32x4_p)data, NCONST_V32_CAST(addr));
+#else
+    VecStore((uint32x4_p)VecReverseLE(data), NCONST_V32_CAST(addr));
+#endif
+}
+
+//@}
+
+/// \name LOGICAL OPERATIONS
+//@{
+
+/// \brief AND two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecAnd() performs <tt>vec1 & vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \par Wraps
+///  vec_and
+/// \sa VecAnd64
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecAnd(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_and(vec1, (T1)vec2);
+}
+
+/// \brief OR two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecOr() performs <tt>vec1 | vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \par Wraps
+///  vec_or
+/// \sa VecOr64
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecOr(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_or(vec1, (T1)vec2);
+}
+
+/// \brief XOR two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecXor() performs <tt>vec1 ^ vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \par Wraps
+///  vec_xor
+/// \sa VecXor64
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecXor(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_xor(vec1, (T1)vec2);
+}
+
+//@}
+
+/// \name ARITHMETIC OPERATIONS
+//@{
+
+/// \brief Add two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecAdd() performs <tt>vec1 + vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \par Wraps
+///  vec_add
+/// \sa VecAdd64
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecAdd(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_add(vec1, (T1)vec2);
+}
+
+/// \brief Subtract two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \details VecSub() performs <tt>vec1 - vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \par Wraps
+///  vec_sub
+/// \sa VecSub64
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecSub(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_sub(vec1, (T1)vec2);
+}
+
+//@}
+
+/// \name PERMUTE OPERATIONS
+//@{
+
+/// \brief Permutes a vector
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec the vector
+/// \param mask vector mask
+/// \return vector
+/// \details VecPermute() creates a new vector from vec according to mask.
+///  mask is an uint8x16_p vector. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_perm
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecPermute(const T1 vec, const T2 mask)
+{
+    return (T1)vec_perm(vec, vec, (uint8x16_p)mask);
+}
+
+/// \brief Permutes two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \param mask vector mask
+/// \return vector
+/// \details VecPermute() creates a new vector from vec1 and vec2 according to mask.
+///  mask is an uint8x16_p vector. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_perm
+/// \since Crypto++ 6.0
+template <class T1, class T2>
+inline T1 VecPermute(const T1 vec1, const T1 vec2, const T2 mask)
+{
+    return (T1)vec_perm(vec1, (T1)vec2, (uint8x16_p)mask);
+}
+
+//@}
+
+/// \name SHIFT AND ROTATE OPERATIONS
+//@{
+
+/// \brief Shift a vector left
+/// \tparam C shift byte count
+/// \tparam T vector type
+/// \param vec the vector
+/// \return vector
+/// \details VecShiftLeftOctet() returns a new vector after shifting the
+///  concatenation of the zero vector and the source vector by the specified
+///  number of bytes. The return vector is the same type as vec.
+/// \details On big endian machines VecShiftLeftOctet() is <tt>vec_sld(a, z,
+///  c)</tt>. On little endian machines VecShiftLeftOctet() is translated to
+///  <tt>vec_sld(z, a, 16-c)</tt>. You should always call the function as
+///  if on a big endian machine as shown below.
+/// <pre>
+///   uint8x16_p x = VecLoad(ptr);
+///   uint8x16_p y = VecShiftLeftOctet<12>(x);
+/// </pre>
+/// \par Wraps
+///  vec_sld
+/// \sa <A HREF="https://stackoverflow.com/q/46341923/608639">Is vec_sld
+///  endian sensitive?</A> on Stack Overflow
+/// \since Crypto++ 6.0
+template <unsigned int C, class T>
+inline T VecShiftLeftOctet(const T vec)
+{
+    const T zero = {0};
+    if (C >= 16)
+    {
+        // Out of range
+        return zero;
+    }
+    else if (C == 0)
+    {
+        // Noop
+        return vec;
+    }
+    else
+    {
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    enum { R=C&0xf };
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)zero, R);
+#else
+    enum { R=(16-C)&0xf };  // Linux xlC 13.1 workaround in Debug builds
+    return (T)vec_sld((uint8x16_p)zero, (uint8x16_p)vec, R);
+#endif
+    }
+}
+
+/// \brief Shift a vector right
+/// \tparam C shift byte count
+/// \tparam T vector type
+/// \param vec the vector
+/// \return vector
+/// \details VecShiftRightOctet() returns a new vector after shifting the
+///  concatenation of the zero vector and the source vector by the specified
+///  number of bytes. The return vector is the same type as vec.
+/// \details On big endian machines VecShiftRightOctet() is <tt>vec_sld(a, z,
+///  c)</tt>. On little endian machines VecShiftRightOctet() is translated to
+///  <tt>vec_sld(z, a, 16-c)</tt>. You should always call the function as
+///  if on a big endian machine as shown below.
+/// <pre>
+///   uint8x16_p x = VecLoad(ptr);
+///   uint8x16_p y = VecShiftRightOctet<12>(y);
+/// </pre>
+/// \par Wraps
+///  vec_sld
+/// \sa <A HREF="https://stackoverflow.com/q/46341923/608639">Is vec_sld
+///  endian sensitive?</A> on Stack Overflow
+/// \since Crypto++ 6.0
+template <unsigned int C, class T>
+inline T VecShiftRightOctet(const T vec)
+{
+    const T zero = {0};
+    if (C >= 16)
+    {
+        // Out of range
+        return zero;
+    }
+    else if (C == 0)
+    {
+        // Noop
+        return vec;
+    }
+    else
+    {
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    enum { R=(16-C)&0xf };  // Linux xlC 13.1 workaround in Debug builds
+    return (T)vec_sld((uint8x16_p)zero, (uint8x16_p)vec, R);
+#else
+    enum { R=C&0xf };
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)zero, R);
+#endif
+    }
+}
+
+/// \brief Rotate a vector left
+/// \tparam C shift byte count
+/// \tparam T vector type
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateLeftOctet() returns a new vector after rotating the
+///  concatenation of the source vector with itself by the specified
+///  number of bytes. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_sld
+/// \sa <A HREF="https://stackoverflow.com/q/46341923/608639">Is vec_sld
+///  endian sensitive?</A> on Stack Overflow
+/// \since Crypto++ 6.0
+template <unsigned int C, class T>
+inline T VecRotateLeftOctet(const T vec)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    enum { R = C&0xf };
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)vec, R);
+#else
+    enum { R=(16-C)&0xf };  // Linux xlC 13.1 workaround in Debug builds
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)vec, R);
+#endif
+}
+
+/// \brief Rotate a vector right
+/// \tparam C shift byte count
+/// \tparam T vector type
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateRightOctet() returns a new vector after rotating the
+///  concatenation of the source vector with itself by the specified
+///  number of bytes. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_sld
+/// \sa <A HREF="https://stackoverflow.com/q/46341923/608639">Is vec_sld
+///  endian sensitive?</A> on Stack Overflow
+/// \since Crypto++ 6.0
+template <unsigned int C, class T>
+inline T VecRotateRightOctet(const T vec)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    enum { R=(16-C)&0xf };  // Linux xlC 13.1 workaround in Debug builds
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)vec, R);
+#else
+    enum { R = C&0xf };
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)vec, R);
+#endif
+}
+
+/// \brief Rotate a vector left
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateLeft() rotates each element in a vector by
+///  bit count. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 7.0
+template<unsigned int C>
+inline uint32x4_p VecRotateLeft(const uint32x4_p vec)
+{
+    const uint32x4_p m = {C, C, C, C};
+    return vec_rl(vec, m);
+}
+
+/// \brief Rotate a vector right
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateRight() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 7.0
+template<unsigned int C>
+inline uint32x4_p VecRotateRight(const uint32x4_p vec)
+{
+    const uint32x4_p m = {32-C, 32-C, 32-C, 32-C};
+    return vec_rl(vec, m);
+}
+
+/// \brief Shift a vector left
+/// \tparam C shift bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecShiftLeft() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_sl
+/// \since Crypto++ 8.1
+template<unsigned int C>
+inline uint32x4_p VecShiftLeft(const uint32x4_p vec)
+{
+    const uint32x4_p m = {C, C, C, C};
+    return vec_sl(vec, m);
+}
+
+/// \brief Shift a vector right
+/// \tparam C shift bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecShiftRight() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.1
+template<unsigned int C>
+inline uint32x4_p VecShiftRight(const uint32x4_p vec)
+{
+    const uint32x4_p m = {C, C, C, C};
+    return vec_sr(vec, m);
+}
+
+// 64-bit elements available at POWER7 with VSX, but vec_rl and vec_sl require POWER8
+#if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+/// \brief Rotate a vector left
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateLeft() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \details VecRotateLeft() with 64-bit elements is available on
+///  POWER8 and above.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.0
+template<unsigned int C>
+inline uint64x2_p VecRotateLeft(const uint64x2_p vec)
+{
+    const uint64x2_p m = {C, C};
+    return vec_rl(vec, m);
+}
+
+/// \brief Shift a vector left
+/// \tparam C shift bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecShiftLeft() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \details VecShiftLeft() with 64-bit elements is available on
+///  POWER8 and above.
+/// \par Wraps
+///  vec_sl
+/// \since Crypto++ 8.1
+template<unsigned int C>
+inline uint64x2_p VecShiftLeft(const uint64x2_p vec)
+{
+    const uint64x2_p m = {C, C};
+    return vec_sl(vec, m);
+}
+
+/// \brief Rotate a vector right
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateRight() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \details VecRotateRight() with 64-bit elements is available on
+///  POWER8 and above.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.0
+template<unsigned int C>
+inline uint64x2_p VecRotateRight(const uint64x2_p vec)
+{
+    const uint64x2_p m = {64-C, 64-C};
+    return vec_rl(vec, m);
+}
+
+/// \brief Shift a vector right
+/// \tparam C shift bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecShiftRight() rotates each element in a vector
+///  by bit count. The return vector is the same type as vec.
+/// \details VecShiftRight() with 64-bit elements is available on
+///  POWER8 and above.
+/// \par Wraps
+///  vec_sr
+/// \since Crypto++ 8.1
+template<unsigned int C>
+inline uint64x2_p VecShiftRight(const uint64x2_p vec)
+{
+    const uint64x2_p m = {C, C};
+    return vec_sr(vec, m);
+}
+
+#endif  // ARCH_PWR8
+
+//@}
+
+/// \name OTHER OPERATIONS
+//@{
+
+/// \brief Merge two vectors
+/// \tparam T vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \par Wraps
+///  vec_mergel
+/// \since Crypto++ 8.1
+template <class T>
+inline T VecMergeLow(const T vec1, const T vec2)
+{
+    return vec_mergel(vec1, vec2);
+}
+
+/// \brief Merge two vectors
+/// \tparam T vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \par Wraps
+///  vec_mergeh
+/// \since Crypto++ 8.1
+template <class T>
+inline T VecMergeHigh(const T vec1, const T vec2)
+{
+    return vec_mergeh(vec1, vec2);
+}
+
+/// \brief Broadcast 32-bit word to a vector
+/// \param val the 32-bit value
+/// \return vector
+/// \par Wraps
+///  vec_splats
+/// \since Crypto++ 8.3
+inline uint32x4_p VecSplatWord(word32 val)
+{
+    // Fix spurious GCC warning???
+    CRYPTOPP_UNUSED(val);
+
+    // Apple Altivec and XL C++ do not offer vec_splats.
+    // GCC offers vec_splats back to -mcpu=power4.
+#if defined(_ARCH_PWR4) && defined(__GNUC__)
+    return vec_splats(val);
+#else
+    //const word32 x[4] = {val,val,val,val};
+    //return VecLoad(x);
+    const word32 x[4] = {val};
+    return vec_splat(VecLoad(x),0);
+#endif
+}
+
+/// \brief Broadcast 32-bit element to a vector
+/// \tparam the element number
+/// \param val the 32-bit value
+/// \return vector
+/// \par Wraps
+///  vec_splat
+/// \since Crypto++ 8.3
+template <unsigned int N>
+inline uint32x4_p VecSplatElement(const uint32x4_p val)
+{
+    return vec_splat(val, N);
+}
+
+#if defined(__VSX__) || defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Broadcast 64-bit double word to a vector
+/// \param val the 64-bit value
+/// \return vector
+/// \par Wraps
+///  vec_splats
+/// \since Crypto++ 8.3
+inline uint64x2_p VecSplatWord(word64 val)
+{
+    // The PPC64 ABI says so.
+    return vec_splats((unsigned long long)val);
+}
+
+/// \brief Broadcast 64-bit element to a vector
+/// \tparam the element number
+/// \param val the 64-bit value
+/// \return vector
+/// \par Wraps
+///  vec_splat
+/// \since Crypto++ 8.3
+template <unsigned int N>
+inline uint64x2_p VecSplatElement(const uint64x2_p val)
+{
+#if defined(__VSX__) || defined(_ARCH_PWR8)
+    return vec_splat(val, N);
+#else
+    enum {E=N&1};
+    if (E == 0)
+    {
+        const uint8x16_p m = {0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7};
+        return vec_perm(val, val, m);
+    }
+    else // (E == 1)
+    {
+        const uint8x16_p m = {8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15};
+        return vec_perm(val, val, m);
+    }
+#endif
+}
+#endif
+
+/// \brief Extract a dword from a vector
+/// \tparam T vector type
+/// \param val the vector
+/// \return vector created from low dword
+/// \details VecGetLow() extracts the low dword from a vector. The low dword
+///  is composed of the least significant bits and occupies bytes 8 through 15
+///  when viewed as a big endian array. The return vector is the same type as
+///  the original vector and padded with 0's in the most significant bit positions.
+/// \par Wraps
+///  vec_sld
+/// \since Crypto++ 7.0
+template <class T>
+inline T VecGetLow(const T val)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN) && (defined(__VSX__) || defined(_ARCH_PWR8))
+    const T zero = {0};
+    return (T)VecMergeLow((uint64x2_p)zero, (uint64x2_p)val);
+#else
+    return VecShiftRightOctet<8>(VecShiftLeftOctet<8>(val));
+#endif
+}
+
+/// \brief Extract a dword from a vector
+/// \tparam T vector type
+/// \param val the vector
+/// \return vector created from high dword
+/// \details VecGetHigh() extracts the high dword from a vector. The high dword
+///  is composed of the most significant bits and occupies bytes 0 through 7
+///  when viewed as a big endian array. The return vector is the same type as
+///  the original vector and padded with 0's in the most significant bit positions.
+/// \par Wraps
+///  vec_sld
+/// \since Crypto++ 7.0
+template <class T>
+inline T VecGetHigh(const T val)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN) && (defined(__VSX__) || defined(_ARCH_PWR8))
+    const T zero = {0};
+    return (T)VecMergeHigh((uint64x2_p)zero, (uint64x2_p)val);
+#else
+    return VecShiftRightOctet<8>(val);
+#endif
+}
+
+/// \brief Exchange high and low double words
+/// \tparam T vector type
+/// \param vec the vector
+/// \return vector
+/// \par Wraps
+///  vec_sld
+/// \since Crypto++ 7.0
+template <class T>
+inline T VecSwapWords(const T vec)
+{
+    return (T)vec_sld((uint8x16_p)vec, (uint8x16_p)vec, 8);
+}
+
+//@}
+
+/// \name COMPARISON
+//@{
+
+/// \brief Compare two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return true if vec1 equals vec2, false otherwise
+/// \details VecEqual() performs a bitwise compare. The vector element types do
+///  not matter.
+/// \par Wraps
+///  vec_all_eq
+/// \since Crypto++ 8.0
+template <class T1, class T2>
+inline bool VecEqual(const T1 vec1, const T2 vec2)
+{
+    return 1 == vec_all_eq((uint32x4_p)vec1, (uint32x4_p)vec2);
+}
+
+/// \brief Compare two vectors
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return true if vec1 does not equal vec2, false otherwise
+/// \details VecNotEqual() performs a bitwise compare. The vector element types do
+///  not matter.
+/// \par Wraps
+///  vec_all_eq
+/// \since Crypto++ 8.0
+template <class T1, class T2>
+inline bool VecNotEqual(const T1 vec1, const T2 vec2)
+{
+    return 0 == vec_all_eq((uint32x4_p)vec1, (uint32x4_p)vec2);
+}
+
+//@}
+
+////////////////// 32-bit Altivec /////////////////
+
+/// \name 32-BIT ALTIVEC
+//@{
+
+/// \brief Add two vectors as if uint64x2_p
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecAdd64() performs <tt>vec1 + vec2</tt>. VecAdd64() performs as
+///  if adding two uint64x2_p vectors. On POWER7 and below VecAdd64() manages
+///  the carries from the elements.
+/// \par Wraps
+///  vec_add for POWER8, vec_addc, vec_perm, vec_add for Altivec
+/// \since Crypto++ 8.3
+inline uint32x4_p VecAdd64(const uint32x4_p& vec1, const uint32x4_p& vec2)
+{
+    // 64-bit elements available at POWER7 with VSX, but addudm requires POWER8
+#if defined(_ARCH_PWR8) && !defined(CRYPTOPP_DEBUG)
+    return (uint32x4_p)vec_add((uint64x2_p)vec1, (uint64x2_p)vec2);
+#else
+    // The carry mask selects carrys for elements 1 and 3 and sets
+    // remaining elements to 0. The results is then shifted so the
+    // carried values are added to elements 0 and 2.
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    const uint32x4_p zero = {0, 0, 0, 0};
+    const uint32x4_p mask = {0, 1, 0, 1};
+#else
+    const uint32x4_p zero = {0, 0, 0, 0};
+    const uint32x4_p mask = {1, 0, 1, 0};
+#endif
+
+    uint32x4_p cy = vec_addc(vec1, vec2);
+    uint32x4_p res = vec_add(vec1, vec2);
+    cy = vec_and(mask, cy);
+    cy = vec_sld (cy, zero, 4);
+    return vec_add(res, cy);
+#endif
+}
+
+#if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Add two vectors as if uint64x2_p
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecAdd64() performs <tt>vec1 + vec2</tt>. VecAdd64() performs as
+///  if adding two uint64x2_p vectors. On POWER7 and below VecAdd64() manages
+///  the carries from the elements.
+/// \par Wraps
+///  vec_add for POWER8
+/// \since Crypto++ 8.3
+inline uint64x2_p VecAdd64(const uint64x2_p& vec1, const uint64x2_p& vec2)
+{
+    // 64-bit elements available at POWER7 with VSX, but addudm requires POWER8
+    const uint64x2_p res = vec_add(vec1, vec2);
+
+#if defined(CRYPTOPP_DEBUG)
+    // Test 32-bit add in debug builds while we are here.
+    const uint32x4_p x = (uint32x4_p)vec1;
+    const uint32x4_p y = (uint32x4_p)vec2;
+    const uint32x4_p r = VecAdd64(x, y);
+
+    CRYPTOPP_ASSERT(vec_all_eq((uint32x4_p)res, r) == 1);
+#endif
+
+    return res;
+}
+#endif
+
+/// \brief Subtract two vectors as if uint64x2_p
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \details VecSub64() performs <tt>vec1 - vec2</tt>. VecSub64() performs as
+///  if subtracting two uint64x2_p vectors. On POWER7 and below VecSub64()
+///  manages the borrows from the elements.
+/// \par Wraps
+///  vec_sub for POWER8, vec_subc, vec_andc, vec_perm, vec_sub for Altivec
+/// \since Crypto++ 8.3
+inline uint32x4_p VecSub64(const uint32x4_p& vec1, const uint32x4_p& vec2)
+{
+#if defined(_ARCH_PWR8) && !defined(CRYPTOPP_DEBUG)
+    // 64-bit elements available at POWER7 with VSX, but subudm requires POWER8
+    return (uint32x4_p)vec_sub((uint64x2_p)vec1, (uint64x2_p)vec2);
+#else
+    // The borrow mask selects borrows for elements 1 and 3 and sets
+    // remaining elements to 0. The results is then shifted so the
+    // borrowed values are subtracted from elements 0 and 2.
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    const uint32x4_p zero = {0, 0, 0, 0};
+    const uint32x4_p mask = {0, 1, 0, 1};
+#else
+    const uint32x4_p zero = {0, 0, 0, 0};
+    const uint32x4_p mask = {1, 0, 1, 0};
+#endif
+
+    // subc sets the complement of borrow, so we have to
+    // un-complement it using andc.
+    uint32x4_p bw = vec_subc(vec1, vec2);
+    uint32x4_p res = vec_sub(vec1, vec2);
+    bw = vec_andc(mask, bw);
+    bw = vec_sld (bw, zero, 4);
+    return vec_sub(res, bw);
+#endif
+}
+
+#if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Subtract two vectors as if uint64x2_p
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \details VecSub64() performs <tt>vec1 - vec2</tt>. VecSub64() performs as
+///  if subtracting two uint64x2_p vectors. On POWER7 and below VecSub64()
+///  manages the borrows from the elements.
+/// \par Wraps
+///  vec_sub for POWER8
+/// \since Crypto++ 8.3
+inline uint64x2_p VecSub64(const uint64x2_p& vec1, const uint64x2_p& vec2)
+{
+    // 64-bit elements available at POWER7 with VSX, but subudm requires POWER8
+    const uint64x2_p res = vec_sub(vec1, vec2);
+
+#if defined(CRYPTOPP_DEBUG)
+    // Test 32-bit sub in debug builds while we are here.
+    const uint32x4_p x = (uint32x4_p)vec1;
+    const uint32x4_p y = (uint32x4_p)vec2;
+    const uint32x4_p r = VecSub64(x, y);
+
+    CRYPTOPP_ASSERT(vec_all_eq((uint32x4_p)res, r) == 1);
+#endif
+
+    return res;
+}
+#endif
+
+/// \brief Rotate a vector left as if uint64x2_p
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateLeft() rotates each element in a vector by bit count.
+///  vec is rotated as if uint64x2_p.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.3
+template<unsigned int C>
+inline uint32x4_p VecRotateLeft64(const uint32x4_p vec)
+{
+#if defined(_ARCH_PWR8) && !defined(CRYPTOPP_DEBUG)
+    // 64-bit elements available at POWER7 with VSX, but vec_rl and vec_sl require POWER8
+    return (uint32x4_p)VecRotateLeft<C>((uint64x2_p)vec);
+#else
+    // C=0, 32, or 64 needs special handling. That is S32 and S64 below.
+    enum {S64=C&63, S32=C&31, BR=(S64>=32)};
+
+    // Get the low bits, shift them to high bits
+    uint32x4_p t1 = VecShiftLeft<S32>(vec);
+    // Get the high bits, shift them to low bits
+    uint32x4_p t2 = VecShiftRight<32-S32>(vec);
+
+    if (S64 == 0)
+    {
+        const uint8x16_p m = {0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15};
+        return VecPermute(vec, m);
+    }
+    else if (S64 == 32)
+    {
+        const uint8x16_p m = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
+        return VecPermute(vec, m);
+    }
+    else if (BR)  // Big rotate amount?
+    {
+        const uint8x16_p m = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
+        t1 = VecPermute(t1, m);
+    }
+    else
+    {
+        const uint8x16_p m = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
+        t2 = VecPermute(t2, m);
+    }
+
+    return vec_or(t1, t2);
+#endif
+}
+
+/// \brief Rotate a vector left as if uint64x2_p
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateLeft<8>() rotates each element in a vector
+///  by 8-bits. vec is rotated as if uint64x2_p. This specialization
+///  is used by algorithms like Speck128.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.3
+template<>
+inline uint32x4_p VecRotateLeft64<8>(const uint32x4_p vec)
+{
+#if (CRYPTOPP_BIG_ENDIAN)
+    const uint8x16_p m = { 1,2,3,4, 5,6,7,0, 9,10,11,12, 13,14,15,8 };
+    return VecPermute(vec, m);
+#else
+    const uint8x16_p m = { 7,0,1,2, 3,4,5,6, 15,8,9,10, 11,12,13,14 };
+    return VecPermute(vec, m);
+#endif
+}
+
+#if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Rotate a vector left as if uint64x2_p
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateLeft64() rotates each element in a vector by
+///  bit count. vec is rotated as if uint64x2_p.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.3
+template<unsigned int C>
+inline uint64x2_p VecRotateLeft64(const uint64x2_p vec)
+{
+    // 64-bit elements available at POWER7 with VSX, but vec_rl and vec_sl require POWER8
+    const uint64x2_p res = VecRotateLeft<C>(vec);
+
+#if defined(CRYPTOPP_DEBUG)
+    // Test 32-bit rotate in debug builds while we are here.
+    const uint32x4_p x = (uint32x4_p)vec;
+    const uint32x4_p r = VecRotateLeft64<C>(x);
+
+    CRYPTOPP_ASSERT(vec_all_eq((uint32x4_p)res, r) == 1);
+#endif
+
+    return res;
+}
+#endif
+
+/// \brief Rotate a vector right as if uint64x2_p
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateRight64() rotates each element in a vector by
+///  bit count. vec is rotated as if uint64x2_p.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.3
+template<unsigned int C>
+inline uint32x4_p VecRotateRight64(const uint32x4_p vec)
+{
+#if defined(_ARCH_PWR8) && !defined(CRYPTOPP_DEBUG)
+    // 64-bit elements available at POWER7 with VSX, but vec_rl and vec_sl require POWER8
+    return (uint32x4_p)VecRotateRight<C>((uint64x2_p)vec);
+#else
+    // C=0, 32, or 64 needs special handling. That is S32 and S64 below.
+    enum {S64=C&63, S32=C&31, BR=(S64>=32)};
+
+    // Get the low bits, shift them to high bits
+    uint32x4_p t1 = VecShiftRight<S32>(vec);
+    // Get the high bits, shift them to low bits
+    uint32x4_p t2 = VecShiftLeft<32-S32>(vec);
+
+    if (S64 == 0)
+    {
+        const uint8x16_p m = {0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15};
+        return VecPermute(vec, m);
+    }
+    else if (S64 == 32)
+    {
+        const uint8x16_p m = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
+        return VecPermute(vec, m);
+    }
+    else if (BR)  // Big rotate amount?
+    {
+        const uint8x16_p m = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
+        t1 = VecPermute(t1, m);
+    }
+    else
+    {
+        const uint8x16_p m = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
+        t2 = VecPermute(t2, m);
+    }
+
+    return vec_or(t1, t2);
+#endif
+}
+
+/// \brief Rotate a vector right as if uint64x2_p
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateRight64<8>() rotates each element in a vector
+///  by 8-bits. vec is rotated as if uint64x2_p. This specialization
+///  is used by algorithms like Speck128.
+/// \details vec is rotated as if uint64x2_p.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.3
+template<>
+inline uint32x4_p VecRotateRight64<8>(const uint32x4_p vec)
+{
+#if (CRYPTOPP_BIG_ENDIAN)
+    const uint8x16_p m = { 7,0,1,2, 3,4,5,6, 15,8,9,10, 11,12,13,14 };
+    return VecPermute(vec, m);
+#else
+    const uint8x16_p m = { 1,2,3,4, 5,6,7,0, 9,10,11,12, 13,14,15,8 };
+    return VecPermute(vec, m);
+#endif
+}
+
+#if defined(__VSX__) || defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Rotate a vector right as if uint64x2_p
+/// \tparam C rotate bit count
+/// \param vec the vector
+/// \return vector
+/// \details VecRotateRight64() rotates each element in a vector by
+///  bit count. vec is rotated as if uint64x2_p.
+/// \par Wraps
+///  vec_rl
+/// \since Crypto++ 8.3
+template<unsigned int C>
+inline uint64x2_p VecRotateRight64(const uint64x2_p vec)
+{
+    // 64-bit elements available at POWER7 with VSX, but vec_rl and vec_sl require POWER8
+    const uint64x2_p res = VecRotateRight<C>(vec);
+
+#if defined(CRYPTOPP_DEBUG)
+    // Test 32-bit rotate in debug builds while we are here.
+    const uint32x4_p x = (uint32x4_p)vec;
+    const uint32x4_p r = VecRotateRight64<C>(x);
+
+    CRYPTOPP_ASSERT(vec_all_eq((uint32x4_p)res, r) == 1);
+#endif
+
+    return res;
+}
+#endif
+
+/// \brief AND two vectors as if uint64x2_p
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecAnd64() performs <tt>vec1 & vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \details VecAnd64() is a convenience function that simply performs a VecAnd().
+/// \par Wraps
+///  vec_and
+/// \since Crypto++ 8.3
+template <class T1, class T2>
+inline T1 VecAnd64(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_and(vec1, (T1)vec2);
+}
+
+/// \brief OR two vectors as if uint64x2_p
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecOr64() performs <tt>vec1 | vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \details VecOr64() is a convenience function that simply performs a VecOr().
+/// \par Wraps
+///  vec_or
+/// \since Crypto++ 8.3
+template <class T1, class T2>
+inline T1 VecOr64(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_or(vec1, (T1)vec2);
+}
+
+/// \brief XOR two vectors as if uint64x2_p
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param vec1 the first vector
+/// \param vec2 the second vector
+/// \return vector
+/// \details VecXor64() performs <tt>vec1 ^ vec2</tt>.
+///  vec2 is cast to the same type as vec1. The return vector
+///  is the same type as vec1.
+/// \details VecXor64() is a convenience function that simply performs a VecXor().
+/// \par Wraps
+///  vec_xor
+/// \since Crypto++ 8.3
+template <class T1, class T2>
+inline T1 VecXor64(const T1 vec1, const T2 vec2)
+{
+    return (T1)vec_xor(vec1, (T1)vec2);
+}
+
+/// \brief Broadcast 64-bit double word to a vector
+/// \param val the 64-bit value
+/// \return vector
+/// \par Wraps
+///  vec_splats
+/// \since Crypto++ 8.3
+inline uint32x4_p VecSplatWord64(word64 val)
+{
+#if defined(_ARCH_PWR8)
+    // The PPC64 ABI says so.
+    return (uint32x4_p)vec_splats((unsigned long long)val);
+#else
+    const word64 x[2] = {val,val};
+    return (uint32x4_p)VecLoad((const word32*)x);
+#endif
+}
+
+/// \brief Broadcast 64-bit element to a vector as if uint64x2_p
+/// \tparam the element number
+/// \param val the 64-bit value
+/// \return vector
+/// \par Wraps
+///  vec_splat
+/// \since Crypto++ 8.3
+template <unsigned int N>
+inline uint32x4_p VecSplatElement64(const uint32x4_p val)
+{
+#if defined(__VSX__) || defined(_ARCH_PWR8)
+    return (uint32x4_p)vec_splat((uint64x2_p)val, N);
+#else
+    enum {E=N&1};
+    if (E == 0)
+    {
+        const uint8x16_p m = {0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7};
+        return (uint32x4_p)vec_perm(val, val, m);
+    }
+    else // (E == 1)
+    {
+        const uint8x16_p m = {8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15};
+        return (uint32x4_p)vec_perm(val, val, m);
+    }
+#endif
+}
+
+#if defined(__VSX__) || defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+/// \brief Broadcast 64-bit element to a vector
+/// \tparam the element number
+/// \param val the 64-bit value
+/// \return vector
+/// \since Crypto++ 8.3
+template <unsigned int N>
+inline uint64x2_p VecSplatElement64(const uint64x2_p val)
+{
+    return vec_splat(val, N);
+}
+#endif
+
+//@}
+
+//////////////////////// Power8 Crypto ////////////////////////
+
+// __CRYPTO__ alone is not enough. Clang will define __CRYPTO__
+// when it is not available, like with Power7. Sigh...
+#if (defined(_ARCH_PWR8) && defined(__CRYPTO__)) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+/// \name POLYNOMIAL MULTIPLICATION
+//@{
+
+/// \brief Polynomial multiplication
+/// \param a the first term
+/// \param b the second term
+/// \return vector product
+/// \details VecPolyMultiply() performs polynomial multiplication. POWER8
+///  polynomial multiplication multiplies the high and low terms, and then
+///  XOR's the high and low products. That is, the result is <tt>ah*bh XOR
+///  al*bl</tt>. It is different behavior than Intel polynomial
+///  multiplication. To obtain a single product without the XOR, then set
+///  one of the high or low terms to 0. For example, setting <tt>ah=0</tt>
+///  results in <tt>0*bh XOR al*bl = al*bl</tt>.
+/// \par Wraps
+///  __vpmsumw, __builtin_altivec_crypto_vpmsumw and __builtin_crypto_vpmsumw.
+/// \since Crypto++ 8.1
+inline uint32x4_p VecPolyMultiply(const uint32x4_p& a, const uint32x4_p& b)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return __vpmsumw (a, b);
+#elif defined(__clang__)
+    return __builtin_altivec_crypto_vpmsumw (a, b);
+#else
+    return __builtin_crypto_vpmsumw (a, b);
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first term
+/// \param b the second term
+/// \return vector product
+/// \details VecPolyMultiply() performs polynomial multiplication. POWER8
+///  polynomial multiplication multiplies the high and low terms, and then
+///  XOR's the high and low products. That is, the result is <tt>ah*bh XOR
+///  al*bl</tt>. It is different behavior than Intel polynomial
+///  multiplication. To obtain a single product without the XOR, then set
+///  one of the high or low terms to 0. For example, setting <tt>ah=0</tt>
+///  results in <tt>0*bh XOR al*bl = al*bl</tt>.
+/// \par Wraps
+///  __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
+/// \since Crypto++ 8.1
+inline uint64x2_p VecPolyMultiply(const uint64x2_p& a, const uint64x2_p& b)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return __vpmsumd (a, b);
+#elif defined(__clang__)
+    return __builtin_altivec_crypto_vpmsumd (a, b);
+#else
+    return __builtin_crypto_vpmsumd (a, b);
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first term
+/// \param b the second term
+/// \return vector product
+/// \details VecIntelMultiply00() performs polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x00)</tt>.
+///  The <tt>0x00</tt> indicates the low 64-bits of <tt>a</tt> and <tt>b</tt>
+///  are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and numbered 0.
+/// \par Wraps
+///  __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
+/// \since Crypto++ 8.0
+inline uint64x2_p VecIntelMultiply00(const uint64x2_p& a, const uint64x2_p& b)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    return VecSwapWords(VecPolyMultiply(VecGetHigh(a), VecGetHigh(b)));
+#else
+    return VecPolyMultiply(VecGetHigh(a), VecGetHigh(b));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first term
+/// \param b the second term
+/// \return vector product
+/// \details VecIntelMultiply01 performs() polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x01)</tt>.
+///  The <tt>0x01</tt> indicates the low 64-bits of <tt>a</tt> and high
+///  64-bits of <tt>b</tt> are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and numbered 0.
+/// \par Wraps
+///  __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
+/// \since Crypto++ 8.0
+inline uint64x2_p VecIntelMultiply01(const uint64x2_p& a, const uint64x2_p& b)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    return VecSwapWords(VecPolyMultiply(a, VecGetHigh(b)));
+#else
+    return VecPolyMultiply(a, VecGetHigh(b));
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first term
+/// \param b the second term
+/// \return vector product
+/// \details VecIntelMultiply10() performs polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x10)</tt>.
+///  The <tt>0x10</tt> indicates the high 64-bits of <tt>a</tt> and low
+///  64-bits of <tt>b</tt> are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and numbered 0.
+/// \par Wraps
+///  __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
+/// \since Crypto++ 8.0
+inline uint64x2_p VecIntelMultiply10(const uint64x2_p& a, const uint64x2_p& b)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    return VecSwapWords(VecPolyMultiply(VecGetHigh(a), b));
+#else
+    return VecPolyMultiply(VecGetHigh(a), b);
+#endif
+}
+
+/// \brief Polynomial multiplication
+/// \param a the first term
+/// \param b the second term
+/// \return vector product
+/// \details VecIntelMultiply11() performs polynomial multiplication and presents
+///  the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x11)</tt>.
+///  The <tt>0x11</tt> indicates the high 64-bits of <tt>a</tt> and <tt>b</tt>
+///  are multiplied.
+/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
+///  is MSB and numbered 127, while the rightmost bit is LSB and numbered 0.
+/// \par Wraps
+///  __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
+/// \since Crypto++ 8.0
+inline uint64x2_p VecIntelMultiply11(const uint64x2_p& a, const uint64x2_p& b)
+{
+#if defined(CRYPTOPP_BIG_ENDIAN)
+    return VecSwapWords(VecPolyMultiply(VecGetLow(a), b));
+#else
+    return VecPolyMultiply(VecGetLow(a), b);
+#endif
+}
+
+//@}
+
+/// \name AES ENCRYPTION
+//@{
+
+/// \brief One round of AES encryption
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param state the state vector
+/// \param key the subkey vector
+/// \details VecEncrypt() performs one round of AES encryption of state
+///  using subkey key. The return vector is the same type as state.
+/// \details VecEncrypt() is available on POWER8 and above.
+/// \par Wraps
+///  __vcipher, __builtin_altivec_crypto_vcipher, __builtin_crypto_vcipher
+/// \since GCC and XLC since Crypto++ 6.0, LLVM Clang since Crypto++ 8.0
+template <class T1, class T2>
+inline T1 VecEncrypt(const T1 state, const T2 key)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return (T1)__vcipher((uint8x16_p)state, (uint8x16_p)key);
+#elif defined(__clang__)
+    return (T1)__builtin_altivec_crypto_vcipher((uint64x2_p)state, (uint64x2_p)key);
+#elif defined(__GNUC__)
+    return (T1)__builtin_crypto_vcipher((uint64x2_p)state, (uint64x2_p)key);
+#else
+    CRYPTOPP_ASSERT(0);
+#endif
+}
+
+/// \brief Final round of AES encryption
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param state the state vector
+/// \param key the subkey vector
+/// \details VecEncryptLast() performs the final round of AES encryption
+///  of state using subkey key. The return vector is the same type as state.
+/// \details VecEncryptLast() is available on POWER8 and above.
+/// \par Wraps
+///  __vcipherlast, __builtin_altivec_crypto_vcipherlast, __builtin_crypto_vcipherlast
+/// \since GCC and XLC since Crypto++ 6.0, LLVM Clang since Crypto++ 8.0
+template <class T1, class T2>
+inline T1 VecEncryptLast(const T1 state, const T2 key)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return (T1)__vcipherlast((uint8x16_p)state, (uint8x16_p)key);
+#elif defined(__clang__)
+    return (T1)__builtin_altivec_crypto_vcipherlast((uint64x2_p)state, (uint64x2_p)key);
+#elif defined(__GNUC__)
+    return (T1)__builtin_crypto_vcipherlast((uint64x2_p)state, (uint64x2_p)key);
+#else
+    CRYPTOPP_ASSERT(0);
+#endif
+}
+
+/// \brief One round of AES decryption
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param state the state vector
+/// \param key the subkey vector
+/// \details VecDecrypt() performs one round of AES decryption of state
+///  using subkey key. The return vector is the same type as state.
+/// \details VecDecrypt() is available on POWER8 and above.
+/// \par Wraps
+///  __vncipher, __builtin_altivec_crypto_vncipher, __builtin_crypto_vncipher
+/// \since GCC and XLC since Crypto++ 6.0, LLVM Clang since Crypto++ 8.0
+template <class T1, class T2>
+inline T1 VecDecrypt(const T1 state, const T2 key)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return (T1)__vncipher((uint8x16_p)state, (uint8x16_p)key);
+#elif defined(__clang__)
+    return (T1)__builtin_altivec_crypto_vncipher((uint64x2_p)state, (uint64x2_p)key);
+#elif defined(__GNUC__)
+    return (T1)__builtin_crypto_vncipher((uint64x2_p)state, (uint64x2_p)key);
+#else
+    CRYPTOPP_ASSERT(0);
+#endif
+}
+
+/// \brief Final round of AES decryption
+/// \tparam T1 vector type
+/// \tparam T2 vector type
+/// \param state the state vector
+/// \param key the subkey vector
+/// \details VecDecryptLast() performs the final round of AES decryption
+///  of state using subkey key. The return vector is the same type as state.
+/// \details VecDecryptLast() is available on POWER8 and above.
+/// \par Wraps
+///  __vncipherlast, __builtin_altivec_crypto_vncipherlast, __builtin_crypto_vncipherlast
+/// \since GCC and XLC since Crypto++ 6.0, LLVM Clang since Crypto++ 8.0
+template <class T1, class T2>
+inline T1 VecDecryptLast(const T1 state, const T2 key)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return (T1)__vncipherlast((uint8x16_p)state, (uint8x16_p)key);
+#elif defined(__clang__)
+    return (T1)__builtin_altivec_crypto_vncipherlast((uint64x2_p)state, (uint64x2_p)key);
+#elif defined(__GNUC__)
+    return (T1)__builtin_crypto_vncipherlast((uint64x2_p)state, (uint64x2_p)key);
+#else
+    CRYPTOPP_ASSERT(0);
+#endif
+}
+
+//@}
+
+/// \name SHA DIGESTS
+//@{
+
+/// \brief SHA256 Sigma functions
+/// \tparam func function
+/// \tparam fmask function mask
+/// \tparam T vector type
+/// \param data the block to transform
+/// \details VecSHA256() selects sigma0, sigma1, Sigma0, Sigma1 based on
+///  func and fmask. The return vector is the same type as data.
+/// \details VecSHA256() is available on POWER8 and above.
+/// \par Wraps
+///  __vshasigmaw, __builtin_altivec_crypto_vshasigmaw, __builtin_crypto_vshasigmaw
+/// \since GCC and XLC since Crypto++ 6.0, LLVM Clang since Crypto++ 8.0
+template <int func, int fmask, class T>
+inline T VecSHA256(const T data)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return (T)__vshasigmaw((uint32x4_p)data, func, fmask);
+#elif defined(__clang__)
+    return (T)__builtin_altivec_crypto_vshasigmaw((uint32x4_p)data, func, fmask);
+#elif defined(__GNUC__)
+    return (T)__builtin_crypto_vshasigmaw((uint32x4_p)data, func, fmask);
+#else
+    CRYPTOPP_ASSERT(0);
+#endif
+}
+
+/// \brief SHA512 Sigma functions
+/// \tparam func function
+/// \tparam fmask function mask
+/// \tparam T vector type
+/// \param data the block to transform
+/// \details VecSHA512() selects sigma0, sigma1, Sigma0, Sigma1 based on
+///  func and fmask. The return vector is the same type as data.
+/// \details VecSHA512() is available on POWER8 and above.
+/// \par Wraps
+///  __vshasigmad, __builtin_altivec_crypto_vshasigmad, __builtin_crypto_vshasigmad
+/// \since GCC and XLC since Crypto++ 6.0, LLVM Clang since Crypto++ 8.0
+template <int func, int fmask, class T>
+inline T VecSHA512(const T data)
+{
+#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
+    return (T)__vshasigmad((uint64x2_p)data, func, fmask);
+#elif defined(__clang__)
+    return (T)__builtin_altivec_crypto_vshasigmad((uint64x2_p)data, func, fmask);
+#elif defined(__GNUC__)
+    return (T)__builtin_crypto_vshasigmad((uint64x2_p)data, func, fmask);
+#else
+    CRYPTOPP_ASSERT(0);
+#endif
+}
+
+//@}
+
+#endif  // __CRYPTO__
+
+#endif  // _ALTIVEC_
+
+NAMESPACE_END
+
+#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic pop
+#endif
+
+#endif  // CRYPTOPP_PPC_CRYPTO_H

+ 3 - 3
include/cryptlib/pssr.h

@@ -1,7 +1,7 @@
 // pssr.h - originally written and placed in the public domain by Wei Dai
 
 /// \file pssr.h
-/// \brief Classes for probablistic signature schemes
+/// \brief Classes for probabilistic signature schemes
 /// \since Crypto++ 2.1
 
 #ifndef CRYPTOPP_PSSR_H
@@ -66,8 +66,8 @@ template<> class PSSR_MEM_BaseWithHashId<false> : public PSSR_MEM_Base {};
 /// \tparam SALT_LEN length of the salt
 /// \tparam MIN_PAD_LEN minimum length of the pad
 /// \tparam USE_HASH_ID flag indicating whether the HashId is used
-/// \details If ALLOW_RECOVERY is true, the the signature scheme provides message recovery. If
-///  ALLOW_RECOVERY is false, the the signature scheme is appendix, and the message must be
+/// \details If ALLOW_RECOVERY is true, the signature scheme provides message recovery. If
+///  ALLOW_RECOVERY is false, the signature scheme is appendix, and the message must be
 ///  provided during verification.
 /// \since Crypto++ 2.1
 template <bool ALLOW_RECOVERY, class MGF=P1363_MGF1, int SALT_LEN=-1, int MIN_PAD_LEN=0, bool USE_HASH_ID=false>

+ 191 - 128
include/cryptlib/pubkey.h

@@ -2,7 +2,7 @@
 
 /// \file pubkey.h
 /// \brief This file contains helper classes/functions for implementing public key algorithms.
-/// \details The class hierachies in this header file tend to look like this:
+/// \details The class hierarchies in this header file tend to look like this:
 ///
 /// <pre>
 ///                   x1
@@ -20,12 +20,12 @@
 /// </pre>
 ///
 /// <ul>
-///   <li>x1, y1, z1 are abstract interface classes defined in cryptlib.h
-///   <li>x2, y2, z2 are implementations of the interfaces using "abstract policies", which
-/// 	  are pure virtual functions that should return interfaces to interchangeable algorithms.
-/// 	  These classes have Base suffixes.
-///   <li>x3, y3, z3 hold actual algorithms and implement those virtual functions.
-/// 	  These classes have Impl suffixes.
+///  <li>x1, y1, z1 are abstract interface classes defined in cryptlib.h
+///  <li>x2, y2, z2 are implementations of the interfaces using "abstract policies", which
+///      are pure virtual functions that should return interfaces to interchangeable algorithms.
+///      These classes have Base suffixes.
+///  <li>x3, y3, z3 hold actual algorithms and implement those virtual functions.
+///      These classes have Impl suffixes.
 /// </ul>
 ///
 /// \details The TF_ prefix means an implementation using trapdoor functions on integers.
@@ -62,41 +62,41 @@ NAMESPACE_BEGIN(CryptoPP)
 
 /// \brief Provides range for plaintext and ciphertext lengths
 /// \details A trapdoor function is a function that is easy to compute in one direction,
-///   but difficult to compute in the opposite direction without special knowledge.
-///   The special knowledge is usually the private key.
+///  but difficult to compute in the opposite direction without special knowledge.
+///  The special knowledge is usually the private key.
 /// \details Trapdoor functions only handle messages of a limited length or size.
-///   MaxPreimage is the plaintext's maximum length, and MaxImage is the
-///   ciphertext's maximum length.
+///  MaxPreimage is the plaintext's maximum length, and MaxImage is the
+///  ciphertext's maximum length.
 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
-///   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
+///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds
 {
 public:
 	virtual ~TrapdoorFunctionBounds() {}
 
 	/// \brief Returns the maximum size of a message before the trapdoor function is applied
-	/// \returns the maximum size of a message before the trapdoor function is applied
+	/// \return the maximum size of a message before the trapdoor function is applied
 	/// \details Derived classes must implement PreimageBound().
 	virtual Integer PreimageBound() const =0;
-	/// \brief Returns the maximum size of a message after the trapdoor function is applied
-	/// \returns the maximum size of a message after the trapdoor function is applied
+	/// \brief Returns the maximum size of a representation after the trapdoor function is applied
+	/// \return the maximum size of a representation after the trapdoor function is applied
 	/// \details Derived classes must implement ImageBound().
 	virtual Integer ImageBound() const =0;
 	/// \brief Returns the maximum size of a message before the trapdoor function is applied bound to a public key
-	/// \returns the maximum size of a message before the trapdoor function is applied bound to a public key
+	/// \return the maximum size of a message before the trapdoor function is applied bound to a public key
 	/// \details The default implementation returns <tt>PreimageBound() - 1</tt>.
 	virtual Integer MaxPreimage() const {return --PreimageBound();}
-	/// \brief Returns the maximum size of a message after the trapdoor function is applied bound to a public key
-	/// \returns the the maximum size of a message after the trapdoor function is applied bound to a public key
+	/// \brief Returns the maximum size of a representation after the trapdoor function is applied bound to a public key
+	/// \return the maximum size of a representation after the trapdoor function is applied bound to a public key
 	/// \details The default implementation returns <tt>ImageBound() - 1</tt>.
 	virtual Integer MaxImage() const {return --ImageBound();}
 };
 
 /// \brief Applies the trapdoor function, using random data if required
 /// \details ApplyFunction() is the foundation for encrypting a message under a public key.
-///   Derived classes will override it at some point.
+///  Derived classes will override it at some point.
 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
-///   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
+///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
 {
 public:
@@ -105,23 +105,23 @@ public:
 	/// \brief Applies the trapdoor function, using random data if required
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param x the message on which the encryption function is applied
-	/// \returns the message x encrypted under the public key
+	/// \return the message x encrypted under the public key
 	/// \details ApplyRandomizedFunction is a generalization of encryption under a public key
-	///    cryptosystem. The RandomNumberGenerator may (or may not) be required.
-	///    Derived classes must implement it.
+	///  cryptosystem. The RandomNumberGenerator may (or may not) be required.
+	///  Derived classes must implement it.
 	virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
 
 	/// \brief Determines if the encryption algorithm is randomized
-	/// \returns true if the encryption algorithm is randomized, false otherwise
+	/// \return true if the encryption algorithm is randomized, false otherwise
 	/// \details If IsRandomized() returns false, then NullRNG() can be used.
 	virtual bool IsRandomized() const {return true;}
 };
 
 /// \brief Applies the trapdoor function
 /// \details ApplyFunction() is the foundation for encrypting a message under a public key.
-///    Derived classes will override it at some point.
+///  Derived classes will override it at some point.
 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
-///   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
+///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction
 {
 public:
@@ -131,26 +131,26 @@ public:
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param x the message on which the encryption function is applied
 	/// \details ApplyRandomizedFunction is a generalization of encryption under a public key
-	///    cryptosystem. The RandomNumberGenerator may (or may not) be required.
-	/// \details Internally, ApplyRandomizedFunction() calls ApplyFunction() \a
-	///   without the RandomNumberGenerator.
+	///  cryptosystem. The RandomNumberGenerator may (or may not) be required.
+	/// \details Internally, ApplyRandomizedFunction() calls ApplyFunction()
+	///  without the RandomNumberGenerator.
 	Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
 		{CRYPTOPP_UNUSED(rng); return ApplyFunction(x);}
 	bool IsRandomized() const {return false;}
 
 	/// \brief Applies the trapdoor
 	/// \param x the message on which the encryption function is applied
-	/// \returns the message x encrypted under the public key
+	/// \return the message x encrypted under the public key
 	/// \details ApplyFunction is a generalization of encryption under a public key
-	///    cryptosystem. Derived classes must implement it.
+	///  cryptosystem. Derived classes must implement it.
 	virtual Integer ApplyFunction(const Integer &x) const =0;
 };
 
 /// \brief Applies the inverse of the trapdoor function, using random data if required
 /// \details CalculateInverse() is the foundation for decrypting a message under a private key
-///   in a public key cryptosystem. Derived classes will override it at some point.
+///  in a public key cryptosystem. Derived classes will override it at some point.
 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
-///   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
+///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse
 {
 public:
@@ -159,22 +159,22 @@ public:
 	/// \brief Applies the inverse of the trapdoor function, using random data if required
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param x the message on which the decryption function is applied
-	/// \returns the message x decrypted under the private key
+	/// \return the message x decrypted under the private key
 	/// \details CalculateRandomizedInverse is a generalization of decryption using the private key
-	///    The RandomNumberGenerator may (or may not) be required. Derived classes must implement it.
+	///  The RandomNumberGenerator may (or may not) be required. Derived classes must implement it.
 	virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
 
 	/// \brief Determines if the decryption algorithm is randomized
-	/// \returns true if the decryption algorithm is randomized, false otherwise
+	/// \return true if the decryption algorithm is randomized, false otherwise
 	/// \details If IsRandomized() returns false, then NullRNG() can be used.
 	virtual bool IsRandomized() const {return true;}
 };
 
 /// \brief Applies the inverse of the trapdoor function
 /// \details CalculateInverse() is the foundation for decrypting a message under a private key
-///   in a public key cryptosystem. Derived classes will override it at some point.
+///  in a public key cryptosystem. Derived classes will override it at some point.
 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
-///   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
+///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
 {
 public:
@@ -183,22 +183,22 @@ public:
 	/// \brief Applies the inverse of the trapdoor function
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param x the message on which the decryption function is applied
-	/// \returns the message x decrypted under the private key
+	/// \return the message x decrypted under the private key
 	/// \details CalculateRandomizedInverse is a generalization of decryption using the private key
-	/// \details Internally, CalculateRandomizedInverse() calls CalculateInverse() \a
-	///   without the RandomNumberGenerator.
+	/// \details Internally, CalculateRandomizedInverse() calls CalculateInverse()
+	///  without the RandomNumberGenerator.
 	Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
 		{return CalculateInverse(rng, x);}
 
 	/// \brief Determines if the decryption algorithm is randomized
-	/// \returns true if the decryption algorithm is randomized, false otherwise
+	/// \return true if the decryption algorithm is randomized, false otherwise
 	/// \details If IsRandomized() returns false, then NullRNG() can be used.
 	bool IsRandomized() const {return false;}
 
 	/// \brief Calculates the inverse of an element
 	/// \param rng a RandomNumberGenerator derived class
 	/// \param x the element
-	/// \returns the inverse of the element in the group
+	/// \return the inverse of the element in the group
 	virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
 };
 
@@ -304,9 +304,9 @@ typedef std::pair<const byte *, unsigned int> HashIdentifier;
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details PK_SignatureMessageEncodingMethod provides interfaces for message
-///   encoding method for public key signature schemes. The methods support both
-///   trapdoor functions (<tt>TF_*</tt>) and discrete logarithm (<tt>DL_*</tt>)
-///   based schemes.
+///  encoding method for public key signature schemes. The methods support both
+///  trapdoor functions (<tt>TF_*</tt>) and discrete logarithm (<tt>DL_*</tt>)
+///  based schemes.
 class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod
 {
 public:
@@ -320,9 +320,9 @@ public:
 	/// \brief Determines whether an encoding method requires a random number generator
 	/// \return true if the encoding method requires a RandomNumberGenerator()
 	/// \details if IsProbabilistic() returns false, then NullRNG() can be passed to functions that take
-	///   RandomNumberGenerator().
+	///  RandomNumberGenerator().
 	/// \sa Bellare and Rogaway<a href="http://grouper.ieee.org/groups/1363/P1363a/contributions/pss-submission.pdf">PSS:
-	///   Provably Secure Encoding Method for Digital Signatures</a>
+	///  Provably Secure Encoding Method for Digital Signatures</a>
 	bool IsProbabilistic() const
 		{return true;}
 	bool AllowNonrecoverablePart() const
@@ -379,7 +379,7 @@ public:
 		{
 			static HashIdentifier CRYPTOPP_API Lookup()
 			{
-				return HashIdentifier((const byte *)NULLPTR, 0);
+				return HashIdentifier(static_cast<const byte *>(NULLPTR), 0);
 			}
 		};
 	};
@@ -387,7 +387,7 @@ public:
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details PK_DeterministicSignatureMessageEncodingMethod provides interfaces
-///   for message encoding method for public key signature schemes.
+///  for message encoding method for public key signature schemes.
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
 {
 public:
@@ -398,7 +398,7 @@ public:
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details PK_RecoverableSignatureMessageEncodingMethod provides interfaces
-///   for message encoding method for public key signature schemes.
+///  for message encoding method for public key signature schemes.
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
 {
 public:
@@ -409,7 +409,7 @@ public:
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details DL_SignatureMessageEncodingMethod_DSA provides interfaces
-///   for message encoding method for DSA.
+///  for message encoding method for DSA.
 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
 {
 public:
@@ -421,7 +421,7 @@ public:
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details DL_SignatureMessageEncodingMethod_NR provides interfaces
-///   for message encoding method for Nyberg-Rueppel.
+///  for message encoding method for Nyberg-Rueppel.
 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
 {
 public:
@@ -434,7 +434,7 @@ public:
 #if 0
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details DL_SignatureMessageEncodingMethod_SM2 provides interfaces
-///   for message encoding method for SM2.
+///  for message encoding method for SM2.
 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_SM2 : public PK_DeterministicSignatureMessageEncodingMethod
 {
 public:
@@ -447,7 +447,7 @@ public:
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details PK_MessageAccumulatorBase provides interfaces
-///   for message encoding method.
+///  for message encoding method.
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator
 {
 public:
@@ -468,7 +468,7 @@ public:
 
 /// \brief Interface for message encoding method for public key signature schemes.
 /// \details PK_MessageAccumulatorBase provides interfaces
-///   for message encoding method.
+///  for message encoding method.
 template <class HASH_ALGORITHM>
 class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
 {
@@ -682,6 +682,8 @@ class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, ty
 // ********************************************************
 
 /// \brief Mask generation function interface
+/// \sa P1363_KDF2, P1363_MGF1
+/// \since Crypto++ 2.0
 class CRYPTOPP_NO_VTABLE MaskGeneratingFunction
 {
 public:
@@ -690,7 +692,7 @@ public:
 	/// \brief Generate and apply mask
 	/// \param hash HashTransformation derived class
 	/// \param output the destination byte array
-	/// \param outputLength the size fo the the destination byte array
+	/// \param outputLength the size of the destination byte array
 	/// \param input the message to hash
 	/// \param inputLength the size of the message
 	/// \param mask flag indicating whether to apply the mask
@@ -701,7 +703,7 @@ public:
 /// \brief P1363 mask generation function
 /// \param hash HashTransformation derived class
 /// \param output the destination byte array
-/// \param outputLength the size fo the the destination byte array
+/// \param outputLength the size of the destination byte array
 /// \param input the message to hash
 /// \param inputLength the size of the message
 /// \param derivationParams additional derivation parameters
@@ -711,10 +713,24 @@ public:
 CRYPTOPP_DLL void CRYPTOPP_API P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart);
 
 /// \brief P1363 mask generation function
+/// \sa P1363_KDF2, MaskGeneratingFunction
+/// \since Crypto++ 2.0
 class P1363_MGF1 : public MaskGeneratingFunction
 {
 public:
+	/// \brief The algorithm name
+	/// \return the algorithm name
+	/// \details StaticAlgorithmName returns the algorithm's name as a static
+	///  member function.
 	CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "MGF1";}
+
+	/// \brief P1363 mask generation function
+	/// \param hash HashTransformation derived class
+	/// \param output the destination byte array
+	/// \param outputLength the size of the destination byte array
+	/// \param input the message to hash
+	/// \param inputLength the size of the message
+	/// \param mask flag indicating whether to apply the mask
 	void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const
 	{
 		P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULLPTR, 0, mask, 0);
@@ -725,10 +741,22 @@ public:
 
 /// \brief P1363 key derivation function
 /// \tparam H hash function used in the derivation
+/// \sa P1363_MGF1, KeyDerivationFunction, <A
+///  HREF="https://www.cryptopp.com/wiki/P1363_KDF2">P1363_KDF2</A>
+///  on the Crypto++ wiki
+/// \since Crypto++ 2.0
 template <class H>
 class P1363_KDF2
 {
 public:
+	/// \brief P1363 key derivation function
+	/// \param output the destination byte array
+	/// \param outputLength the size of the destination byte array
+	/// \param input the message to hash
+	/// \param inputLength the size of the message
+	/// \param derivationParams additional derivation parameters
+	/// \param derivationParamsLength the size of the additional derivation parameters
+	/// \details DeriveKey calls P1363_MGF1KDF2_Common
 	static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength)
 	{
 		H h;
@@ -770,7 +798,9 @@ public:
 		if (m_validationLevel > level)
 			return true;
 
+		CRYPTOPP_ASSERT(ValidateGroup(rng, level));
 		bool pass = ValidateGroup(rng, level);
+		CRYPTOPP_ASSERT(ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation()));
 		pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation());
 
 		m_validationLevel = pass ? level+1 : 0;
@@ -793,11 +823,11 @@ public:
 
 	/// \brief Perform precomputation
 	/// \param precomputationStorage the suggested number of objects for the precompute table
-	/// \throws NotImplemented
+	/// \throw NotImplemented
 	/// \details The exact semantics of Precompute() varies, but it typically means calculate
-	///   a table of n objects that can be used later to speed up computation.
+	///  a table of n objects that can be used later to speed up computation.
 	/// \details If a derived class does not override Precompute(), then the base class throws
-	///   NotImplemented.
+	///  NotImplemented.
 	/// \sa SupportsPrecomputation(), LoadPrecomputation(), SavePrecomputation()
 	void Precompute(unsigned int precomputationStorage=16)
 	{
@@ -806,7 +836,7 @@ public:
 
 	/// \brief Retrieve previously saved precomputation
 	/// \param storedPrecomputation BufferedTransformation with the saved precomputation
-	/// \throws NotImplemented
+	/// \throw NotImplemented
 	/// \sa SupportsPrecomputation(), Precompute()
 	void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
 	{
@@ -816,7 +846,7 @@ public:
 
 	/// \brief Save precomputation for later use
 	/// \param storedPrecomputation BufferedTransformation to write the precomputation
-	/// \throws NotImplemented
+	/// \throw NotImplemented
 	/// \sa SupportsPrecomputation(), Precompute()
 	void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
 	{
@@ -842,7 +872,7 @@ public:
 	}
 
 	/// \brief Exponentiates an element
-	/// \param base the base elemenet
+	/// \param base the base element
 	/// \param exponent the exponent to raise the base
 	/// \return the result of the exponentiation
 	/// \details Internally, ExponentiateElement() calls SimultaneousExponentiate().
@@ -886,8 +916,8 @@ public:
 	/// \brief Retrieves the encoded element's size
 	/// \param reversible flag indicating the encoding format
 	/// \return encoded element's size, in bytes
-	/// \details The format of the encoded element varies by the underlyinhg type of the element and the
-	///   reversible flag. GetEncodedElementSize() must be implemented in a derived class.
+	/// \details The format of the encoded element varies by the underlying type of the element and the
+	///  reversible flag. GetEncodedElementSize() must be implemented in a derived class.
 	/// \sa GetEncodedElementSize(), EncodeElement(), DecodeElement()
 	virtual unsigned int GetEncodedElementSize(bool reversible) const =0;
 
@@ -918,14 +948,14 @@ public:
 	/// \param level level of thoroughness
 	/// \return true if the tests succeed, false otherwise
 	/// \details There are four levels of thoroughness:
-	///   <ul>
-	///   <li>0 - using this object won't cause a crash or exception
-	///   <li>1 - this object will probably function, and encrypt, sign, other operations correctly
-	///   <li>2 - ensure this object will function correctly, and perform reasonable security checks
-	///   <li>3 - perform reasonable security checks, and do checks that may take a long time
-	///   </ul>
+	///  <ul>
+	///  <li>0 - using this object won't cause a crash or exception
+	///  <li>1 - this object will probably function, and encrypt, sign, other operations correctly
+	///  <li>2 - ensure this object will function correctly, and perform reasonable security checks
+	///  <li>3 - perform reasonable security checks, and do checks that may take a long time
+	///  </ul>
 	/// \details Level 0 does not require a RandomNumberGenerator. A NullRNG() can be used for level 0.
-	///   Level 1 may not check for weak keys and such. Levels 2 and 3 are recommended.
+	///  Level 1 may not check for weak keys and such. Levels 2 and 3 are recommended.
 	/// \details ValidateGroup() must be implemented in a derived class.
 	virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0;
 
@@ -935,14 +965,14 @@ public:
 	/// \param precomp optional pointer to DL_FixedBasePrecomputation
 	/// \return true if the tests succeed, false otherwise
 	/// \details There are four levels of thoroughness:
-	///   <ul>
-	///   <li>0 - using this object won't cause a crash or exception
-	///   <li>1 - this object will probably function, and encrypt, sign, other operations correctly
-	///   <li>2 - ensure this object will function correctly, and perform reasonable security checks
-	///   <li>3 - perform reasonable security checks, and do checks that may take a long time
-	///   </ul>
+	///  <ul>
+	///  <li>0 - using this object won't cause a crash or exception
+	///  <li>1 - this object will probably function, and encrypt, sign, other operations correctly
+	///  <li>2 - ensure this object will function correctly, and perform reasonable security checks
+	///  <li>3 - perform reasonable security checks, and do checks that may take a long time
+	///  </ul>
 	/// \details Level 0 performs group membership checks. Level 1 may not check for weak keys and such.
-	///   Levels 2 and 3 are recommended.
+	///  Levels 2 and 3 are recommended.
 	/// \details ValidateElement() must be implemented in a derived class.
 	virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const =0;
 
@@ -952,7 +982,7 @@ public:
 	/// \param element element to check
 	/// \return true if the element is an identity, false otherwise
 	/// \details The identity element or or neutral element is a special element in a group that leaves
-	///   other elements unchanged when combined with it.
+	///  other elements unchanged when combined with it.
 	/// \details IsIdentity() must be implemented in a derived class.
 	virtual bool IsIdentity(const Element &element) const =0;
 
@@ -962,7 +992,7 @@ public:
 	/// \param exponents an array of exponents
 	/// \param exponentsCount the number of exponents in the array
 	/// \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the
-	///   result at the respective position in the results array.
+	///  result at the respective position in the results array.
 	/// \details SimultaneousExponentiate() must be implemented in a derived class.
 	/// \pre <tt>COUNTOF(results) == exponentsCount</tt>
 	/// \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
@@ -1038,24 +1068,24 @@ public:
 	/// \param name the name of the object or value to retrieve
 	/// \param valueType reference to a variable that receives the value
 	/// \param pValue void pointer to a variable that receives the value
-	/// \returns true if the value was retrieved, false otherwise
+	/// \return true if the value was retrieved, false otherwise
 	/// \details GetVoidValue() retrieves the value of name if it exists.
 	/// \note GetVoidValue() is an internal function and should be implemented
-	///   by derived classes. Users should use one of the other functions instead.
+	///  by derived classes. Users should use one of the other functions instead.
 	/// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(),
-	///   GetRequiredParameter() and GetRequiredIntParameter()
+	///  GetRequiredParameter() and GetRequiredIntParameter()
 	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
 	{
 		return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
 				CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement);
 	}
 
-	/// \brief Initialize or reinitialize this this key
+	/// \brief Initialize or reinitialize this key
 	/// \param source NameValuePairs to assign
 	void AssignFrom(const NameValuePairs &source);
 
 	/// \brief Retrieves the public element
-	/// \returns the public element
+	/// \return the public element
 	virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());}
 
 	/// \brief Sets the public element
@@ -1064,7 +1094,7 @@ public:
 
 	/// \brief Exponentiates this element
 	/// \param exponent the exponent to raise the base
-	/// \returns the public element raised to the exponent
+	/// \return the public element raised to the exponent
 	virtual Element ExponentiatePublicElement(const Integer &exponent) const
 	{
 		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
@@ -1074,9 +1104,9 @@ public:
 	/// \brief Exponentiates an element
 	/// \param baseExp the first exponent
 	/// \param publicExp the second exponent
-	/// \returns the public element raised to the exponent
+	/// \return the public element raised to the exponent
 	/// \details CascadeExponentiateBaseAndPublicElement raises the public element to
-	///   the base element and precomputation.
+	///  the base element and precomputation.
 	virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const
 	{
 		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
@@ -1085,14 +1115,14 @@ public:
 
 	/// \brief Accesses the public precomputation
 	/// \details GetPublicPrecomputation returns a const reference, while
-	///   AccessPublicPrecomputation returns a non-const reference. Must be
-	///   overridden in derived classes.
+	///  AccessPublicPrecomputation returns a non-const reference. Must be
+	///  overridden in derived classes.
 	virtual const DL_FixedBasePrecomputation<T> & GetPublicPrecomputation() const =0;
 
 	/// \brief Accesses the public precomputation
 	/// \details GetPublicPrecomputation returns a const reference, while
-	///   AccessPublicPrecomputation returns a non-const reference. Must be
-	///   overridden in derived classes.
+	///  AccessPublicPrecomputation returns a non-const reference. Must be
+	///  overridden in derived classes.
 	virtual DL_FixedBasePrecomputation<T> & AccessPublicPrecomputation() =0;
 };
 
@@ -1123,19 +1153,19 @@ public:
 	/// \param name the name of the object or value to retrieve
 	/// \param valueType reference to a variable that receives the value
 	/// \param pValue void pointer to a variable that receives the value
-	/// \returns true if the value was retrieved, false otherwise
+	/// \return true if the value was retrieved, false otherwise
 	/// \details GetVoidValue() retrieves the value of name if it exists.
 	/// \note GetVoidValue() is an internal function and should be implemented
-	///   by derived classes. Users should use one of the other functions instead.
+	///  by derived classes. Users should use one of the other functions instead.
 	/// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(),
-	///   GetRequiredParameter() and GetRequiredIntParameter()
+	///  GetRequiredParameter() and GetRequiredIntParameter()
 	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
 	{
 		return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
 				CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent);
 	}
 
-	/// \brief Initialize or reinitialize this this key
+	/// \brief Initialize or reinitialize this key
 	/// \param source NameValuePairs to assign
 	void AssignFrom(const NameValuePairs &source)
 	{
@@ -1145,7 +1175,7 @@ public:
 	}
 
 	/// \brief Retrieves the private exponent
-	/// \returns the private exponent
+	/// \return the private exponent
 	/// \details Must be overridden in derived classes.
 	virtual const Integer & GetPrivateExponent() const =0;
 	/// \brief Sets the private exponent
@@ -1215,14 +1245,21 @@ public:
 	// GeneratableCryptoMaterial
 	bool Validate(RandomNumberGenerator &rng, unsigned int level) const
 	{
+		CRYPTOPP_ASSERT(GetAbstractGroupParameters().Validate(rng, level));
 		bool pass = GetAbstractGroupParameters().Validate(rng, level);
 
 		const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder();
 		const Integer &x = GetPrivateExponent();
 
+		CRYPTOPP_ASSERT(x.IsPositive());
+		CRYPTOPP_ASSERT(x < q);
 		pass = pass && x.IsPositive() && x < q;
+
 		if (level >= 1)
+		{
+			CRYPTOPP_ASSERT(Integer::Gcd(x, q) == Integer::One());
 			pass = pass && Integer::Gcd(x, q) == Integer::One();
+		}
 		return pass;
 	}
 
@@ -1305,7 +1342,9 @@ public:
 	// CryptoMaterial
 	bool Validate(RandomNumberGenerator &rng, unsigned int level) const
 	{
+		CRYPTOPP_ASSERT(GetAbstractGroupParameters().Validate(rng, level));
 		bool pass = GetAbstractGroupParameters().Validate(rng, level);
+		CRYPTOPP_ASSERT(GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation()));
 		pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation());
 		return pass;
 	}
@@ -1361,7 +1400,8 @@ template<class GP>
 DL_PublicKeyImpl<GP>::~DL_PublicKeyImpl() {}
 
 /// \brief Interface for Elgamal-like signature algorithms
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm
 {
@@ -1408,7 +1448,7 @@ public:
 		{return params.GetSubgroupOrder().ByteCount();}
 
 	/// \brief Signature scheme flag
-	/// \returns true if the signature scheme is deterministic, false otherwise
+	/// \return true if the signature scheme is deterministic, false otherwise
 	/// \details IsDeterministic() is provided for DL signers. It is used by RFC 6979 signature schemes.
 	virtual bool IsDeterministic() const
 		{return false;}
@@ -1429,7 +1469,9 @@ public:
 };
 
 /// \brief Interface for DL key agreement algorithms
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
+/// \sa DLIES, ECIES, ECIES_P1363
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm
 {
@@ -1443,7 +1485,9 @@ public:
 };
 
 /// \brief Interface for key derivation algorithms used in DL cryptosystems
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
+/// \sa DLIES, ECIES, ECIES_P1363
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm
 {
@@ -1456,6 +1500,7 @@ public:
 };
 
 /// \brief Interface for symmetric encryption algorithms used in DL cryptosystems
+/// \sa DLIES, ECIES, ECIES_P1363
 class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm
 {
 public:
@@ -1492,7 +1537,7 @@ protected:
 /// \tparam INTFACE PK_Signer or PK_Verifier derived class
 /// \tparam KEY_INTFACE DL_Base key base used in the scheme
 /// \details DL_SignatureSchemeBase provides common functions for signers and verifiers.
-///   DL_Base<DL_PrivateKey> is used for signers, and DL_Base<DL_PublicKey> is used for verifiers.
+///  DL_Base<DL_PrivateKey> is used for signers, and DL_Base<DL_PublicKey> is used for verifiers.
 template <class INTFACE, class KEY_INTFACE>
 class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTFACE, public DL_Base<KEY_INTFACE>
 {
@@ -1500,7 +1545,7 @@ public:
 	virtual ~DL_SignatureSchemeBase() {}
 
 	/// \brief Provides the signature length
-	/// \returns signature length, in bytes
+	/// \return signature length, in bytes
 	/// \details SignatureLength returns the size required for <tt>r+s</tt>.
 	size_t SignatureLength() const
 	{
@@ -1509,29 +1554,29 @@ public:
 	}
 
 	/// \brief Provides the maximum recoverable length
-	/// \returns maximum recoverable length, in bytes
+	/// \return maximum recoverable length, in bytes
 	size_t MaxRecoverableLength() const
 		{return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());}
 
 	/// \brief Provides the maximum recoverable length
-	/// \param signatureLength the size fo the signature
-	/// \returns maximum recoverable length based on signature length, in bytes
+	/// \param signatureLength the size of the signature
+	/// \return maximum recoverable length based on signature length, in bytes
 	/// \details this function is not implemented and always returns 0.
 	size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
 		{CRYPTOPP_UNUSED(signatureLength); CRYPTOPP_ASSERT(false); return 0;}	// TODO
 
 	/// \brief Determines if the scheme is probabilistic
-	/// \returns true if the scheme is probabilistic, false otherwise
+	/// \return true if the scheme is probabilistic, false otherwise
 	bool IsProbabilistic() const
 		{return true;}
 
 	/// \brief Determines if the scheme has non-recoverable part
-	/// \returns true if the message encoding has a non-recoverable part, false otherwise.
+	/// \return true if the message encoding has a non-recoverable part, false otherwise.
 	bool AllowNonrecoverablePart() const
 		{return GetMessageEncodingInterface().AllowNonrecoverablePart();}
 
 	/// \brief Determines if the scheme allows recoverable part first
-	/// \returns true if the message encoding allows the recoverable part, false otherwise.
+	/// \return true if the message encoding allows the recoverable part, false otherwise.
 	bool RecoverablePartFirst() const
 		{return GetMessageEncodingInterface().RecoverablePartFirst();}
 
@@ -1549,7 +1594,8 @@ protected:
 };
 
 /// \brief Discrete Log (DL) signature scheme signer base implementation
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> >
 {
@@ -1604,10 +1650,10 @@ public:
 		if (rng.CanIncorporateEntropy())
 			rng.IncorporateEntropy(representative, representative.size());
 
-		Integer k;
+		Integer k, ks;
+		const Integer& q = params.GetSubgroupOrder();
 		if (alg.IsDeterministic())
 		{
-			const Integer& q = params.GetSubgroupOrder();
 			const Integer& x = key.GetPrivateExponent();
 			const DeterministicSignatureAlgorithm& det = dynamic_cast<const DeterministicSignatureAlgorithm&>(alg);
 			k = det.GenerateRandom(x, q, e);
@@ -1617,8 +1663,15 @@ public:
 			k.Randomize(rng, 1, params.GetSubgroupOrder()-1);
 		}
 
+		// Due to timing attack on nonce length by Jancar
+		// https://github.com/weidai11/cryptopp/issues/869
+		ks = k + q;
+		if (ks.BitCount() == q.BitCount()) {
+			ks += q;
+		}
+
 		Integer r, s;
-		r = params.ConvertElementToInteger(params.ExponentiateBase(k));
+		r = params.ConvertElementToInteger(params.ExponentiateBase(ks));
 		alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
 
 		/*
@@ -1630,7 +1683,7 @@ public:
 		alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s);
 		*/
 
-		size_t rLen = alg.RLen(params);
+		const size_t rLen = alg.RLen(params);
 		r.Encode(signature, rLen);
 		s.Encode(signature+rLen, alg.SLen(params));
 
@@ -1659,7 +1712,8 @@ protected:
 };
 
 /// \brief Discret Log (DL) Verifier base class
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> >
 {
@@ -1668,14 +1722,21 @@ public:
 
 	void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
 	{
-		CRYPTOPP_UNUSED(signature); CRYPTOPP_UNUSED(signatureLength);
 		PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
 		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
 		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
 
-		size_t rLen = alg.RLen(params);
+		// Validation due to https://github.com/weidai11/cryptopp/issues/981
+		// We allow a caller to provide R and S in oversized buffer. R and S
+		// are read based on the field element size, and not the buffer size.
+		const size_t rLen = alg.RLen(params);
+		const size_t sLen = alg.SLen(params);
+		CRYPTOPP_ASSERT(signatureLength >= rLen + sLen);
+		if (signatureLength < rLen + sLen)
+			throw InvalidDataFormat("DL_VerifierBase: signature length is not valid.");
+
 		ma.m_semisignature.Assign(signature, rLen);
-		ma.m_s.Decode(signature+rLen, alg.SLen(params));
+		ma.m_s.Decode(signature+rLen, sLen);
 
 		this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size());
 	}
@@ -1763,7 +1824,8 @@ protected:
 };
 
 /// \brief Discrete Log (DL) decryptor base implementation
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> >
 {
@@ -1803,7 +1865,8 @@ public:
 };
 
 /// \brief Discrete Log (DL) encryptor base implementation
-/// \tparam T Field element
+/// \tparam T Field element type or class
+/// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.
 template <class T>
 class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> >
 {
@@ -2044,7 +2107,7 @@ public:
 	}
 
 	/// \brief Retrieves a reference to the group generator
-	/// \returns const reference to the group generator
+	/// \return const reference to the group generator
 	const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();}
 
 protected:
@@ -2056,17 +2119,17 @@ protected:
 /// \brief Methods for avoiding "Small-Subgroup" attacks on Diffie-Hellman Key Agreement
 /// \details Additional methods exist and include public key validation and choice of prime p.
 /// \sa <A HREF="http://tools.ietf.org/html/rfc2785">Methods for Avoiding the "Small-Subgroup" Attacks on the
-///   Diffie-Hellman Key Agreement Method for S/MIME</A>
+///  Diffie-Hellman Key Agreement Method for S/MIME</A>
 enum CofactorMultiplicationOption {
 	/// \brief No cofactor multiplication applied
 	NO_COFACTOR_MULTIPLICTION,
 	/// \brief Cofactor multiplication compatible with ordinary Diffie-Hellman
 	/// \details Modifies the computation of ZZ by including j (the cofactor) in the computations and is
-	///   compatible with ordinary Diffie-Hellman.
+	///  compatible with ordinary Diffie-Hellman.
 	COMPATIBLE_COFACTOR_MULTIPLICTION,
 	/// \brief Cofactor multiplication incompatible with ordinary Diffie-Hellman
 	/// \details Modifies the computation of ZZ by including j (the cofactor) in the computations but is
-	///   not compatible with ordinary Diffie-Hellman.
+	///  not compatible with ordinary Diffie-Hellman.
 	INCOMPATIBLE_COFACTOR_MULTIPLICTION};
 
 typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication;
@@ -2207,12 +2270,12 @@ public:
 
 /// \brief Base class for public key encryption standard classes.
 /// \details These classes are used to select from variants of algorithms.
-///   Not all standards apply to all algorithms.
+///  Not all standards apply to all algorithms.
 struct EncryptionStandard {};
 
 /// \brief Base class for public key signature standard classes.
 /// \details These classes are used to select from variants of algorithms.
-///   Not all standards apply to all algorithms.
+///  Not all standards apply to all algorithms.
 struct SignatureStandard {};
 
 /// \brief Trapdoor Function (TF) encryption scheme

Some files were not shown because too many files changed in this diff