diff --git a/.gitmodules b/.gitmodules index d01256c2..c8ced6e4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -76,9 +76,6 @@ [submodule "third_party/fdk-aac"] path = third_party/fdk-aac url = https://github.com/Panda3DS-emu/fdk-aac/ -[submodule "third_party/cryptoppwin"] - path = third_party/cryptoppwin - url = https://github.com/shadps4-emu/ext-cryptoppwin [submodule "third_party/oaknut"] path = third_party/oaknut url = https://github.com/panda3ds-emu/oaknut diff --git a/third_party/cryptoppwin b/third_party/cryptoppwin deleted file mode 160000 index bc3441dd..00000000 --- a/third_party/cryptoppwin +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bc3441dd2d6a9728e747dc0180bc8b9065a2923c diff --git a/third_party/cryptoppwin/CMakeLists.txt b/third_party/cryptoppwin/CMakeLists.txt new file mode 100644 index 00000000..926fb483 --- /dev/null +++ b/third_party/cryptoppwin/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(cryptoppwin SHARED IMPORTED GLOBAL) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set_target_properties(cryptoppwin PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/cryptlibd.lib") +else() + set_target_properties(cryptoppwin PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/cryptlib.lib") +endif() \ No newline at end of file diff --git a/third_party/cryptoppwin/README.md b/third_party/cryptoppwin/README.md new file mode 100644 index 00000000..3a32b2c9 --- /dev/null +++ b/third_party/cryptoppwin/README.md @@ -0,0 +1,7 @@ +# ext-cryptoppwin + +cryptopp library for windows + +This is the place for crypopp static library for linking with windows when using clang compiler with msvc since it is not supported + + diff --git a/third_party/cryptoppwin/include/cryptopp/3way.h b/third_party/cryptoppwin/include/cryptopp/3way.h new file mode 100644 index 00000000..868fa8ca --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/3way.h @@ -0,0 +1,63 @@ +// 3way.h - originally written and placed in the public domain by Wei Dai + +/// \file 3way.h +/// \brief Classes for the 3-Way block cipher + +#ifndef CRYPTOPP_THREEWAY_H +#define CRYPTOPP_THREEWAY_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief ThreeWay block cipher information +struct ThreeWay_Info : public FixedBlockSize<12>, public FixedKeyLength<12>, public VariableRounds<11> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "3-Way";} +}; + +/// \brief ThreeWay block cipher +/// \sa 3-Way +class ThreeWay : public ThreeWay_Info, public BlockCipherDocumentation +{ + /// \brief Class specific implementation and overrides used to operate the cipher. + /// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + + protected: + unsigned int m_rounds; + FixedSizeSecBlock m_k; + }; + + /// \brief Class specific methods used to operate the cipher in the forward direction. + /// \details Implementations and overrides in \p Enc apply to \p ENCRYPTION. + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief Class specific methods used to operate the cipher in the reverse direction. + /// \details Implementations and overrides in \p Dec apply to \p DECRYPTION. + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef ThreeWay::Encryption ThreeWayEncryption; +typedef ThreeWay::Decryption ThreeWayDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/adler32.h b/third_party/cryptoppwin/include/cryptopp/adler32.h new file mode 100644 index 00000000..39f8deb5 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/adler32.h @@ -0,0 +1,33 @@ +// adler32.h - originally written and placed in the public domain by Wei Dai + +/// \file adler32.h +/// \brief Class file for ADLER-32 checksum calculations + +#ifndef CRYPTOPP_ADLER32_H +#define CRYPTOPP_ADLER32_H + +#include "cryptlib.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// ADLER-32 checksum calculations +class Adler32 : public HashTransformation +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE = 4); + Adler32() {Reset();} + 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 "Adler32";} + std::string AlgorithmName() const {return StaticAlgorithmName();} + +private: + void Reset() {m_s1 = 1; m_s2 = 0;} + + word16 m_s1, m_s2; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/adv_simd.h b/third_party/cryptoppwin/include/cryptopp/adv_simd.h new file mode 100644 index 00000000..963d58ee --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#endif + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +# include +# include +#endif + +// SunCC needs CRYPTOPP_SSSE3_AVAILABLE, too +#if (CRYPTOPP_SSSE3_AVAILABLE) +# include +# include +# include +#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 +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(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(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(inBlocks)[15]++; + + func1(block, subKeys, static_cast(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 +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(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(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(inBlocks)[15]++; + + func1(block, subKeys, static_cast(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 +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(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(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(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(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(inBlocks)[15]++; + + func2(block, zero, subKeys, static_cast(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 Issue +/// 224, SunCC and failed compile for rijndael.cpp +# define MAYBE_CONST const +/// \brief SunCC workaround +/// \details SunCC loses the const on AES_Enc_Block and AES_Dec_Block +/// \sa Issue +/// 224, SunCC and failed compile for rijndael.cpp +# define MAYBE_UNCONST_CAST(T, x) (x) +#elif (__SUNPRO_CC >= 0x5130) +# define MAYBE_CONST +# define MAYBE_UNCONST_CAST(T, x) const_cast(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 Issue +/// 20670, _mm_loadu_si128 parameter has wrong type +# define M128_CAST(x) ((__m128i *)(void *)(x)) +/// \brief Clang workaround +/// \details Clang issues spurious alignment warnings +/// \sa Issue +/// 20670, _mm_loadu_si128 parameter has wrong type +# 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 +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(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(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(inBlocks)[15]++; + + func2(block, zero, subKeys, static_cast(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 +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(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(inBlocks)[15]++; + + func1(block, subKeys, static_cast(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 +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(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(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 +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(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(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 diff --git a/third_party/cryptoppwin/include/cryptopp/aes.h b/third_party/cryptoppwin/include/cryptopp/aes.h new file mode 100644 index 00000000..bcc5cf7e --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/aes.h @@ -0,0 +1,30 @@ +// aes.h - originally written and placed in the public domain by Wei Dai + +/// \file +/// \brief Class file for the AES cipher (Rijndael) +/// \details AES is a typdef for Rijndael classes. All key sizes are supported. +/// The library only provides Rijndael with 128-bit blocks, and not 192-bit or 256-bit blocks +/// \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 + +#ifndef CRYPTOPP_AES_H +#define CRYPTOPP_AES_H + +#include "rijndael.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief AES block cipher (Rijndael) +/// \details AES is a typdef for Rijndael classes. All key sizes are supported. +/// The library only provides Rijndael with 128-bit blocks, and not 192-bit or 256-bit blocks +/// \sa AES 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); + +typedef RijndaelEncryption AESEncryption; +typedef RijndaelDecryption AESDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/aes_armv4.h b/third_party/cryptoppwin/include/cryptopp/aes_armv4.h new file mode 100644 index 00000000..000dfec9 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 */ diff --git a/third_party/cryptoppwin/include/cryptopp/algebra.h b/third_party/cryptoppwin/include/cryptopp/algebra.h new file mode 100644 index 00000000..1e04dfff --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/algebra.h @@ -0,0 +1,453 @@ +// algebra.h - originally written and placed in the public domain by Wei Dai + +/// \file algebra.h +/// \brief Classes for performing mathematics over different fields + +#ifndef CRYPTOPP_ALGEBRA_H +#define CRYPTOPP_ALGEBRA_H + +#include "config.h" +#include "integer.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +class Integer; + +/// \brief Abstract group +/// \tparam T element class or type +/// \details const Element& returned by member functions are references +/// to internal data members. Since each object may have only +/// one such data member for holding results, the following code +/// will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// But this should be fine: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+template class CRYPTOPP_NO_VTABLE AbstractGroup +{ +public: + typedef T Element; + + virtual ~AbstractGroup() {} + + /// \brief Compare two elements for equality + /// \param a first element + /// \param b second element + /// \return true if the elements are equal, false otherwise + /// \details Equal() tests the elements for equality using a==b + virtual bool Equal(const Element &a, const Element &b) const =0; + + /// \brief Provides 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 + /// \return the sum of a and b + virtual const Element& Add(const Element &a, const Element &b) const =0; + + /// \brief Inverts the element in the group + /// \param a first element + /// \return the inverse of the element + virtual const Element& Inverse(const Element &a) const =0; + + /// \brief Determine if inversion is fast + /// \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 + /// \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 + /// \return the difference of a and b. The element a 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 + /// \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 + /// \return the reduced element + virtual Element& Reduce(Element &a, const Element &b) const; + + /// \brief Performs a scalar multiplication + /// \param a multiplicand + /// \param e multiplier + /// \return the product + virtual Element ScalarMultiply(const Element &a, const Integer &e) const; + + /// \brief TODO + /// \param x first multiplicand + /// \param e1 the first multiplier + /// \param y second multiplicand + /// \param e2 the second multiplier + /// \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 + /// \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 SimultaneousMultiply() multiplies the base to each exponent in the exponents array and stores the + /// result at the respective position in the results array. + /// \details SimultaneousMultiply() must be implemented in a derived class. + /// \pre COUNTOF(results) == exponentsCount + /// \pre COUNTOF(exponents) == exponentsCount + virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; +}; + +/// \brief Abstract ring +/// \tparam T element class or type +/// \details const Element& returned by member functions are references +/// to internal data members. Since each object may have only +/// one such data member for holding results, the following code +/// will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// But this should be fine: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+template class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup +{ +public: + typedef T Element; + + /// \brief Construct an AbstractRing + AbstractRing() {m_mg.m_pRing = this;} + + /// \brief Copy construct an AbstractRing + /// \param source other AbstractRing + AbstractRing(const AbstractRing &source) + {CRYPTOPP_UNUSED(source); m_mg.m_pRing = this;} + + /// \brief Assign an AbstractRing + /// \param source other AbstractRing + AbstractRing& operator=(const AbstractRing &source) + {CRYPTOPP_UNUSED(source); return *this;} + + /// \brief Determines whether an element is a unit in the group + /// \param a the element + /// \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 + /// \return the multiplicative identity + virtual const Element& MultiplicativeIdentity() const =0; + + /// \brief Multiplies elements in the group + /// \param a the multiplicand + /// \param b the multiplier + /// \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 + /// \param a the element + virtual const Element& MultiplicativeInverse(const Element &a) const =0; + + /// \brief Square an element in the group + /// \param a the element + /// \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 + /// \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 + /// \return the exponentiation + virtual Element Exponentiate(const Element &a, const Integer &e) const; + + /// \brief TODO + /// \param x first element + /// \param e1 first exponent + /// \param y second element + /// \param e2 second exponent + /// \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 + /// \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 COUNTOF(results) == exponentsCount + /// \pre COUNTOF(exponents) == exponentsCount + virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + + /// \brief Retrieves the multiplicative group + /// \return the multiplicative group + virtual const AbstractGroup& MultiplicativeGroup() const + {return m_mg;} + +private: + class MultiplicativeGroupT : public AbstractGroup + { + public: + const AbstractRing& GetRing() const + {return *m_pRing;} + + bool Equal(const Element &a, const Element &b) const + {return GetRing().Equal(a, b);} + + const Element& Identity() const + {return GetRing().MultiplicativeIdentity();} + + const Element& Add(const Element &a, const Element &b) const + {return GetRing().Multiply(a, b);} + + Element& Accumulate(Element &a, const Element &b) const + {return a = GetRing().Multiply(a, b);} + + const Element& Inverse(const Element &a) const + {return GetRing().MultiplicativeInverse(a);} + + const Element& Subtract(const Element &a, const Element &b) const + {return GetRing().Divide(a, b);} + + Element& Reduce(Element &a, const Element &b) const + {return a = GetRing().Divide(a, b);} + + const Element& Double(const Element &a) const + {return GetRing().Square(a);} + + Element ScalarMultiply(const Element &a, const Integer &e) const + {return GetRing().Exponentiate(a, e);} + + Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const + {return GetRing().CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const + {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);} + + const AbstractRing *m_pRing; + }; + + MultiplicativeGroupT m_mg; +}; + +// ******************************************************** + +/// \brief Base and exponent +/// \tparam T base class or type +/// \tparam E exponent class or type +template +struct BaseAndExponent +{ +public: + BaseAndExponent() {} + BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {} + bool operator<(const BaseAndExponent &rhs) const {return exponent < rhs.exponent;} + T base; + E exponent; +}; + +// VC60 workaround: incomplete member template support +template + Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end); +template + Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end); + +// ******************************************************** + +/// \brief Abstract Euclidean domain +/// \tparam T element class or type +/// \details const Element& returned by member functions are references +/// to internal data members. Since each object may have only +/// one such data member for holding results, the following code +/// will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// But this should be fine: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+template class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing +{ +public: + typedef T Element; + + /// \brief Performs the division algorithm on two elements in the ring + /// \param r the remainder + /// \param q the quotient + /// \param a the dividend + /// \param d the divisor + virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0; + + /// \brief Performs a modular reduction in the ring + /// \param a the element + /// \param b the modulus + /// \return the result of a%b. + 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 + /// \return the greatest common denominator of a and b. + virtual const Element& Gcd(const Element &a, const Element &b) const; + +protected: + mutable Element result; +}; + +// ******************************************************** + +/// \brief Euclidean domain +/// \tparam T element class or type +/// \details const Element& returned by member functions are references +/// to internal data members. Since each object may have only +/// one such data member for holding results, the following code +/// will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// But this should be fine: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+template class EuclideanDomainOf : public AbstractEuclideanDomain +{ +public: + typedef T Element; + + EuclideanDomainOf() {} + + bool Equal(const Element &a, const Element &b) const + {return a==b;} + + const Element& Identity() const + {return Element::Zero();} + + const Element& Add(const Element &a, const Element &b) const + {return result = a+b;} + + Element& Accumulate(Element &a, const Element &b) const + {return a+=b;} + + const Element& Inverse(const Element &a) const + {return result = -a;} + + const Element& Subtract(const Element &a, const Element &b) const + {return result = a-b;} + + Element& Reduce(Element &a, const Element &b) const + {return a-=b;} + + const Element& Double(const Element &a) const + {return result = a.Doubled();} + + const Element& MultiplicativeIdentity() const + {return Element::One();} + + const Element& Multiply(const Element &a, const Element &b) const + {return result = a*b;} + + const Element& Square(const Element &a) const + {return result = a.Squared();} + + bool IsUnit(const Element &a) const + {return a.IsUnit();} + + const Element& MultiplicativeInverse(const Element &a) const + {return result = a.MultiplicativeInverse();} + + const Element& Divide(const Element &a, const Element &b) const + {return result = a/b;} + + const Element& Mod(const Element &a, const Element &b) const + {return result = a%b;} + + void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const + {Element::Divide(r, q, a, d);} + + bool operator==(const EuclideanDomainOf &rhs) const + {CRYPTOPP_UNUSED(rhs); return true;} + +private: + mutable Element result; +}; + +/// \brief Quotient ring +/// \tparam T element class or type +/// \details const Element& returned by member functions are references +/// to internal data members. Since each object may have only +/// one such data member for holding results, the following code +/// will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// But this should be fine: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+template class QuotientRing : public AbstractRing +{ +public: + typedef T EuclideanDomain; + typedef typename T::Element Element; + + QuotientRing(const EuclideanDomain &domain, const Element &modulus) + : m_domain(domain), m_modulus(modulus) {} + + const EuclideanDomain & GetDomain() const + {return m_domain;} + + const Element& GetModulus() const + {return m_modulus;} + + bool Equal(const Element &a, const Element &b) const + {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());} + + const Element& Identity() const + {return m_domain.Identity();} + + const Element& Add(const Element &a, const Element &b) const + {return m_domain.Add(a, b);} + + Element& Accumulate(Element &a, const Element &b) const + {return m_domain.Accumulate(a, b);} + + const Element& Inverse(const Element &a) const + {return m_domain.Inverse(a);} + + const Element& Subtract(const Element &a, const Element &b) const + {return m_domain.Subtract(a, b);} + + Element& Reduce(Element &a, const Element &b) const + {return m_domain.Reduce(a, b);} + + const Element& Double(const Element &a) const + {return m_domain.Double(a);} + + bool IsUnit(const Element &a) const + {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));} + + const Element& MultiplicativeIdentity() const + {return m_domain.MultiplicativeIdentity();} + + const Element& Multiply(const Element &a, const Element &b) const + {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);} + + const Element& Square(const Element &a) const + {return m_domain.Mod(m_domain.Square(a), m_modulus);} + + const Element& MultiplicativeInverse(const Element &a) const; + + bool operator==(const QuotientRing &rhs) const + {return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;} + +protected: + EuclideanDomain m_domain; + Element m_modulus; +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "algebra.cpp" +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/algparam.h b/third_party/cryptoppwin/include/cryptopp/algparam.h new file mode 100644 index 00000000..72dae198 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/algparam.h @@ -0,0 +1,520 @@ +// algparam.h - originally written and placed in the public domain by Wei Dai + +/// \file algparam.h +/// \brief Classes for working with NameValuePairs + +#ifndef CRYPTOPP_ALGPARAM_H +#define CRYPTOPP_ALGPARAM_H + +#include "config.h" +#include "cryptlib.h" + +#include "smartptr.h" +#include "secblock.h" +#include "integer.h" +#include "misc.h" + +#include +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Used to pass byte array input as part of a NameValuePairs object +class ConstByteArrayParameter +{ +public: + /// \brief Construct a ConstByteArrayParameter + /// \param data a C-String + /// \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 + ConstByteArrayParameter(const char *data = NULLPTR, bool deepCopy = false) + : m_deepCopy(false), m_data(NULLPTR), m_size(0) + { + Assign(reinterpret_cast(data), data ? strlen(data) : 0, deepCopy); + } + + /// \brief Construct a ConstByteArrayParameter + /// \param data a memory buffer + /// \param size the length of the memory buffer + /// \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 + ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false) + : m_deepCopy(false), m_data(NULLPTR), m_size(0) + { + Assign(data, size, deepCopy); + } + + /// \brief Construct a ConstByteArrayParameter + /// \tparam T a std::basic_string or std::vector class + /// \param string a std::basic_string or std::vector 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 + template ConstByteArrayParameter(const T &string, bool deepCopy = false) + : m_deepCopy(false), m_data(NULLPTR), m_size(0) + { + CRYPTOPP_COMPILE_ASSERT(sizeof(typename T::value_type) == 1); + Assign(reinterpret_cast(&string[0]), string.size(), deepCopy); + } + + /// \brief Assign contents from a memory buffer + /// \param data a memory buffer + /// \param size the length of the memory buffer + /// \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 + void Assign(const byte *data, size_t size, bool deepCopy) + { + // This fires, which means: no data with a size, or data with no size. + // CRYPTOPP_ASSERT((data && size) || !(data || size)); + if (deepCopy) + m_block.Assign(data, size); + else + { + m_data = data; + m_size = size; + } + m_deepCopy = deepCopy; + } + + /// \brief Pointer to the first byte in the memory block + const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;} + /// \brief Pointer beyond the last byte in the memory block + const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;} + /// \brief Length of the memory block + size_t size() const {return m_deepCopy ? m_block.size() : m_size;} + +private: + bool m_deepCopy; + const byte *m_data; + size_t m_size; + SecByteBlock m_block; +}; + +/// \brief Used to pass byte array input as part of a NameValuePairs object +class ByteArrayParameter +{ +public: + /// \brief Construct a ByteArrayParameter + /// \param data a memory buffer + /// \param size the length of the memory buffer + ByteArrayParameter(byte *data = NULLPTR, unsigned int size = 0) + : m_data(data), m_size(size) {} + + /// \brief Construct a ByteArrayParameter + /// \param block a SecByteBlock + ByteArrayParameter(SecByteBlock &block) + : m_data(block.begin()), m_size(block.size()) {} + + /// \brief Pointer to the first byte in the memory block + byte *begin() const {return m_data;} + /// \brief Pointer beyond the last byte in the memory block + byte *end() const {return m_data + m_size;} + /// \brief Length of the memory block + size_t size() const {return m_size;} + +private: + byte *m_data; + size_t m_size; +}; + +/// \brief Combines two sets of NameValuePairs +/// \details CombinedNameValuePairs allows you to provide two sets of of NameValuePairs. +/// If a name is not found in the first set, then the second set is searched for the +/// name and value pair. The second set of NameValuePairs often provides default values. +class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs +{ +public: + /// \brief Construct a CombinedNameValuePairs + /// \param pairs1 reference to the first set of NameValuePairs + /// \param pairs2 reference to the second set of NameValuePairs + CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2) + : m_pairs1(pairs1), m_pairs2(pairs2) {} + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + +private: + const NameValuePairs &m_pairs1, &m_pairs2; +}; + +#ifndef CRYPTOPP_DOXYGEN_PROCESSING +template +class GetValueHelperClass +{ +public: + GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst) + : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false) + { + if (strcmp(m_name, "ValueNames") == 0) + { + m_found = m_getValueNames = true; + NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType); + if (searchFirst) + searchFirst->GetVoidValue(m_name, valueType, pValue); + if (typeid(T) != typeid(BASE)) + pObject->BASE::GetVoidValue(m_name, valueType, pValue); + ((*reinterpret_cast(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';'; + } + + if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType); + *reinterpret_cast(pValue) = pObject; + m_found = true; + return; + } + + if (!m_found && searchFirst) + m_found = searchFirst->GetVoidValue(m_name, valueType, pValue); + + if (!m_found && typeid(T) != typeid(BASE)) + m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue); + } + + operator bool() const {return m_found;} + + template + GetValueHelperClass & operator()(const char *name, const R & (T::*pm)() const) + { + if (m_getValueNames) + (*reinterpret_cast(m_pValue) += name) += ";"; + if (!m_found && strcmp(name, m_name) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType); + *reinterpret_cast(m_pValue) = (m_pObject->*pm)(); + m_found = true; + } + return *this; + } + + GetValueHelperClass &Assignable() + { +#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason + if (m_getValueNames) + ((*reinterpret_cast(m_pValue) += "ThisObject:") += typeid(T).name()) += ';'; + if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType); + *reinterpret_cast(m_pValue) = *m_pObject; + m_found = true; + } +#endif + return *this; + } + +private: + const T *m_pObject; + const char *m_name; + const std::type_info *m_valueType; + void *m_pValue; + bool m_found, m_getValueNames; +}; + +template +GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULLPTR) +{ + return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); +} + +template +GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULLPTR) +{ + return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); +} + +// ******************************************************** + +template +class AssignFromHelperClass +{ +public: + AssignFromHelperClass(T *pObject, const NameValuePairs &source) + : m_pObject(pObject), m_source(source), m_done(false) + { + if (source.GetThisObject(*pObject)) + m_done = true; + else if (typeid(BASE) != typeid(T)) + pObject->BASE::AssignFrom(source); + } + + template + AssignFromHelperClass & operator()(const char *name, void (T::*pm)(const R&)) + { + if (!m_done) + { + R value; + if (!m_source.GetValue(name, value)) + throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'"); + (m_pObject->*pm)(value); + } + return *this; + } + + template + AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(const R&, const S&)) + { + if (!m_done) + { + R value1; + if (!m_source.GetValue(name1, value1)) + throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'"); + S value2; + if (!m_source.GetValue(name2, value2)) + throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'"); + (m_pObject->*pm)(value1, value2); + } + return *this; + } + +private: + T *m_pObject; + const NameValuePairs &m_source; + bool m_done; +}; + +template +AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source) +{ + return AssignFromHelperClass(pObject, source); +} + +template +AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source) +{ + return AssignFromHelperClass(pObject, source); +} + +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +// ******************************************************** + +#ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER +// Allow the linker to discard Integer code if not needed. +// Also see http://github.com/weidai11/cryptopp/issues/389. +CRYPTOPP_DLL bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt); +#endif + +CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId(); + +/// \brief Base class for AlgorithmParameters +class CRYPTOPP_DLL AlgorithmParametersBase +{ +public: + /// \brief Exception thrown when an AlgorithmParameter is unused + class ParameterNotUsed : public Exception + { + public: + ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {} + }; + + virtual ~AlgorithmParametersBase() CRYPTOPP_THROW + { + +#if defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS) + if (std::uncaught_exceptions() == 0) +#elif defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION) + if (std::uncaught_exception() == false) +#else + try +#endif + { + if (m_throwIfNotUsed && !m_used) + throw ParameterNotUsed(m_name); + } +#if !defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION) +# if !defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS) + catch(const Exception&) + { + } +# endif +#endif + } + + // this is actually a move, not a copy + AlgorithmParametersBase(const AlgorithmParametersBase &x) + : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used) + { + m_next.reset(const_cast(x).m_next.release()); + x.m_used = true; + } + + /// \brief Construct a AlgorithmParametersBase + /// \param name the parameter name + /// \param throwIfNotUsed flags indicating whether an exception should be thrown + /// \details If throwIfNotUsed is true, then a ParameterNotUsed exception + /// will be thrown in the destructor if the parameter is not not retrieved. + AlgorithmParametersBase(const char *name, bool throwIfNotUsed) + : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {} + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + +protected: + friend class AlgorithmParameters; + void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60 + + virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0; + virtual void MoveInto(void *p) const =0; // not really const + + const char *m_name; + bool m_throwIfNotUsed; + mutable bool m_used; + member_ptr m_next; +}; + +/// \brief Template base class for AlgorithmParameters +/// \tparam T the class or type +template +class AlgorithmParametersTemplate : public AlgorithmParametersBase +{ +public: + /// \brief Construct an AlgorithmParametersTemplate + /// \param name the name of the value + /// \param value a reference to the value + /// \param throwIfNotUsed flags indicating whether an exception should be thrown + /// \details If throwIfNotUsed is true, then a ParameterNotUsed exception + /// will be thrown in the destructor if the parameter is not not retrieved. + AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed) + : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value) + { + } + + void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const + { +#ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER + // Special case for retrieving an Integer parameter when an int was passed in + if (!(typeid(T) == typeid(int) && AssignIntToInteger(valueType, pValue, &m_value))) +#endif + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType); + *reinterpret_cast(pValue) = m_value; + } + } + +#if defined(DEBUG_NEW) && (CRYPTOPP_MSC_VERSION >= 1300) +# pragma push_macro("new") +# undef new +#endif + + void MoveInto(void *buffer) const + { + AlgorithmParametersTemplate* p = new(buffer) AlgorithmParametersTemplate(*this); + CRYPTOPP_UNUSED(p); // silence warning + } + +#if defined(DEBUG_NEW) && (CRYPTOPP_MSC_VERSION >= 1300) +# pragma pop_macro("new") +#endif + +protected: + T m_value; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; + +/// \brief An object that implements NameValuePairs +/// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by +/// repeatedly using operator() on the object returned by MakeParameters, for example: +///
+///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
+///   
+class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs +{ +public: + /// \brief Construct a AlgorithmParameters + /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by + /// repeatedly using operator() on the object returned by MakeParameters, for example: + ///
+	///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
+	///   
+ AlgorithmParameters(); + +#ifdef __BORLANDC__ + /// \brief Construct a AlgorithmParameters + /// \tparam T the class or type + /// \param name the name of the object or value to retrieve + /// \param value reference to a variable that receives the value + /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed + /// \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(), + /// such as MSVC 7.0 and earlier. + /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by + /// repeatedly using operator() on the object returned by MakeParameters, for example: + ///
+	///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
+	///   
+ template + AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true) + : m_next(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)) + , m_defaultThrowIfNotUsed(throwIfNotUsed) + { + } +#endif + + AlgorithmParameters(const AlgorithmParameters &x); + + AlgorithmParameters & operator=(const AlgorithmParameters &x); + + /// \tparam T the class or type + /// \param name the name of the object or value to retrieve + /// \param value reference to a variable that receives the value + /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed + template + AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed) + { + member_ptr p(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)); + p->m_next.reset(m_next.release()); + m_next.reset(p.release()); + m_defaultThrowIfNotUsed = throwIfNotUsed; + return *this; + } + + /// \brief Appends a NameValuePair to a collection of NameValuePairs + /// \tparam T the class or type + /// \param name the name of the object or value to retrieve + /// \param value reference to a variable that receives the value + template + AlgorithmParameters & operator()(const char *name, const T &value) + { + return operator()(name, value, m_defaultThrowIfNotUsed); + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + +protected: + member_ptr m_next; + bool m_defaultThrowIfNotUsed; +}; + +/// \brief Create an object that implements NameValuePairs +/// \tparam T the class or type +/// \param name the name of the object or value to retrieve +/// \param value reference to a variable that receives the value +/// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed +/// \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(), +/// such as MSVC 7.0 and earlier. +/// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by +/// repeatedly using \p operator() on the object returned by \p MakeParameters, for example: +///
+///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
+///   
+#ifdef __BORLANDC__ +typedef AlgorithmParameters MakeParameters; +#else +template +AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true) +{ + return AlgorithmParameters()(name, value, throwIfNotUsed); +} +#endif + +#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name) +#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name) +#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2) + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/allocate.h b/third_party/cryptoppwin/include/cryptopp/allocate.h new file mode 100644 index 00000000..b106b078 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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, +/// Issue 779 +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, +/// Issue 779 +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, +/// Issue 779 +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, +/// Issue 779 +CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *ptr); + +NAMESPACE_END + +#endif // CRYPTOPP_ALLOCATE_H diff --git a/third_party/cryptoppwin/include/cryptopp/arc4.h b/third_party/cryptoppwin/include/cryptopp/arc4.h new file mode 100644 index 00000000..ca444ce4 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/arc4.h @@ -0,0 +1,89 @@ +// arc4.h - originally written and placed in the public domain by Wei Dai + +/// \file arc4.h +/// \brief Classes for ARC4 cipher +/// \since Crypto++ 3.1 + +#ifndef CRYPTOPP_ARC4_H +#define CRYPTOPP_ARC4_H + +#include "cryptlib.h" +#include "strciphr.h" +#include "secblock.h" +#include "smartptr.h" + +NAMESPACE_BEGIN(CryptoPP) + +namespace Weak1 { + +/// \brief ARC4 base class +/// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions +/// \since Crypto++ 3.1 +class CRYPTOPP_NO_VTABLE ARC4_Base : public VariableKeyLength<16, 1, 256>, public RandomNumberGenerator, public SymmetricCipher, public SymmetricCipherDocumentation +{ +public: + ~ARC4_Base(); + + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "ARC4";} + + void GenerateBlock(byte *output, size_t size); + void DiscardBytes(size_t n); + + void ProcessData(byte *outString, const byte *inString, size_t length); + + bool IsRandomAccess() const {return false;} + bool IsSelfInverting() const {return true;} + bool IsForwardTransformation() const {return true;} + + typedef SymmetricCipherFinal Encryption; + typedef SymmetricCipherFinal Decryption; + +protected: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + virtual unsigned int GetDefaultDiscardBytes() const {return 0;} + + FixedSizeSecBlock m_state; + byte m_x, m_y; +}; + +/// \brief Alleged RC4 +/// \sa Alleged RC4 +/// \since Crypto++ 3.1 +DOCUMENTED_TYPEDEF(SymmetricCipherFinal, ARC4); + +/// \brief MARC4 base class +/// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions +/// \details MARC4 discards the first 256 bytes of keystream, which may be weaker than the rest +/// \since Crypto++ 3.1 +class CRYPTOPP_NO_VTABLE MARC4_Base : public ARC4_Base +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "MARC4";} + + typedef SymmetricCipherFinal Encryption; + typedef SymmetricCipherFinal Decryption; + +protected: + unsigned int GetDefaultDiscardBytes() const {return 256;} +}; + +/// \brief Modified Alleged RC4 +/// \sa Alleged RC4 +/// \since Crypto++ 3.1 +DOCUMENTED_TYPEDEF(SymmetricCipherFinal, MARC4); + +} +#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1 +namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak +#else +using namespace Weak1; // import Weak1 into CryptoPP with warning +#ifdef __GNUC__ +#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning." +#else +#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.") +#endif +#endif + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/argnames.h b/third_party/cryptoppwin/include/cryptopp/argnames.h new file mode 100644 index 00000000..4f929d5d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/argnames.h @@ -0,0 +1,99 @@ +// argnames.h - originally written and placed in the public domain by Wei Dai + +/// \file argnames.h +/// \brief Standard names for retrieving values by name when working with \p NameValuePairs + +#ifndef CRYPTOPP_ARGNAMES_H +#define CRYPTOPP_ARGNAMES_H + +#include "cryptlib.h" + +NAMESPACE_BEGIN(CryptoPP) + +DOCUMENTED_NAMESPACE_BEGIN(Name) + +#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;} + +CRYPTOPP_DEFINE_NAME_STRING(ValueNames) ///< string, a list of value names with a semicolon (';') after each name +CRYPTOPP_DEFINE_NAME_STRING(Version) ///< int +CRYPTOPP_DEFINE_NAME_STRING(Seed) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Key) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(IV) ///< ConstByteArrayParameter, also accepts const byte * for backwards compatibility +CRYPTOPP_DEFINE_NAME_STRING(StolenIV) ///< byte * +CRYPTOPP_DEFINE_NAME_STRING(Nonce) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Rounds) ///< int +CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) ///< int +CRYPTOPP_DEFINE_NAME_STRING(WordSize) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(BlockSize) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) ///< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(KeySize) ///< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) ///< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) ///< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)///< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(Modulus) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(PublicElement) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(Cofactor) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) ///< Integer, ECP::Point, or EC2N::Point +CRYPTOPP_DEFINE_NAME_STRING(Curve) ///< ECP or EC2N +CRYPTOPP_DEFINE_NAME_STRING(GroupOID) ///< OID +CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) ///< const PrimeSelector * +CRYPTOPP_DEFINE_NAME_STRING(Prime1) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(Prime2) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) ///< Integer +CRYPTOPP_DEFINE_NAME_STRING(PutMessage) ///< bool +CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) ///< int +CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) ///< StreamTransformationFilter::BlockPaddingScheme +CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) ///< word32 +CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) ///< word32 +CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) ///< word32 +CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) ///< ByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(InputFileName) ///< const char * +CRYPTOPP_DEFINE_NAME_STRING(InputFileNameWide) ///< const wchar_t * +CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) ///< std::istream * +CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) ///< bool +CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) ///< const char * +CRYPTOPP_DEFINE_NAME_STRING(OutputFileNameWide) ///< const wchar_t * +CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) ///< std::ostream * +CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) ///< bool +CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Separator) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Terminator) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Uppercase) ///< bool +CRYPTOPP_DEFINE_NAME_STRING(GroupSize) ///< int +CRYPTOPP_DEFINE_NAME_STRING(Pad) ///< bool +CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) ///< byte +CRYPTOPP_DEFINE_NAME_STRING(Log2Base) ///< int +CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) ///< const byte * +CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) ///< const byte * +CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) ///< bool +CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) ///< int +CRYPTOPP_DEFINE_NAME_STRING(DigestSize) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(TableSize) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(Blinding) ///< bool, timing attack mitigations, ON by default +CRYPTOPP_DEFINE_NAME_STRING(DerivedKey) ///< ByteArrayParameter, key derivation, derived key +CRYPTOPP_DEFINE_NAME_STRING(DerivedKeyLength) ///< int, key derivation, derived key length in bytes +CRYPTOPP_DEFINE_NAME_STRING(Personalization) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(PersonalizationSize) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(Salt) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Tweak) ///< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(SaltSize) ///< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(TreeMode) ///< byte +CRYPTOPP_DEFINE_NAME_STRING(FileName) ///< const char * +CRYPTOPP_DEFINE_NAME_STRING(FileTime) ///< int +CRYPTOPP_DEFINE_NAME_STRING(Comment) ///< const char * +CRYPTOPP_DEFINE_NAME_STRING(Identity) ///< ConstByteArrayParameter +DOCUMENTED_NAMESPACE_END + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/aria.h b/third_party/cryptoppwin/include/cryptopp/aria.h new file mode 100644 index 00000000..da623a16 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/aria.h @@ -0,0 +1,71 @@ +// aria.h - written and placed in the public domain by Jeffrey Walton + +/// \file aria.h +/// \brief Classes for the ARIA block cipher +/// \details The Crypto++ ARIA implementation is based on the 32-bit implementation by Aaram Yun +/// from the National Security Research Institute, KOREA. Aaram Yun's implementation is based on +/// the 8-bit implementation by Jin Hong. The source files are available in ARIA.zip from the Korea +/// Internet & Security Agency website. +/// \sa RFC 5794, A Description of the ARIA Encryption Algorithm, +/// Korea +/// Internet & Security Agency homepage + +#ifndef CRYPTOPP_ARIA_H +#define CRYPTOPP_ARIA_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief ARIA block cipher information +/// \since Crypto++ 6.0 +struct ARIA_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "ARIA";} +}; + +/// \brief ARIA block cipher +/// \details The Crypto++ ARIA implementation is based on the 32-bit implementation by Aaram Yun +/// from the National Security Research Institute, KOREA. Aaram Yun's implementation is based on +/// the 8-bit implementation by Jin Hong. The source files are available in ARIA.zip from the Korea +/// Internet & Security Agency website. +/// \sa RFC 5794, A Description of the ARIA Encryption Algorithm, +/// Korea +/// Internet & Security Agency homepage +/// \sa ARIA +/// \since Crypto++ 6.0 +class ARIA : public ARIA_Info, public BlockCipherDocumentation +{ +public: + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + Base() : m_rounds(0) {} + + protected: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + private: + // Reference implementation allocates a table of 17 round keys. + typedef SecBlock > AlignedByteBlock; + typedef SecBlock > AlignedWordBlock; + + AlignedWordBlock m_rk; // round keys + AlignedWordBlock m_w; // w0, w1, w2, w3, t and u + unsigned int m_rounds; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef ARIA::Encryption ARIAEncryption; +typedef ARIA::Decryption ARIADecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/arm_simd.h b/third_party/cryptoppwin/include/cryptopp/arm_simd.h new file mode 100644 index 00000000..b8eabe15 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 +# include +#endif + +#if (CRYPTOPP_ARM_ACLE_HEADER) +# include +# include +#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 c = _mm_clmulepi64_si128(a, b, 0x00). +/// The 0x00 indicates the low 64-bits of a and b +/// 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 c = _mm_clmulepi64_si128(a, b, 0x01). +/// The 0x01 indicates the low 64-bits of a and high +/// 64-bits of b 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 c = _mm_clmulepi64_si128(a, b, 0x10). +/// The 0x10 indicates the high 64-bits of a and low +/// 64-bits of b 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 c = _mm_clmulepi64_si128(a, b, 0x11). +/// The 0x11 indicates the high 64-bits of a and b +/// 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 C bytes of vector +/// a and the remaining bytes in b. VEXT_U8 is provided +/// as GCC inline assembly due to Clang and lack of support for the intrinsic. +/// \since Crypto++ 8.0 +template +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 +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 diff --git a/third_party/cryptoppwin/include/cryptopp/asn.h b/third_party/cryptoppwin/include/cryptopp/asn.h new file mode 100644 index 00000000..beb20cd0 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/asn.h @@ -0,0 +1,974 @@ +// asn.h - originally written and placed in the public domain by Wei Dai + +/// \file asn.h +/// \brief Classes and functions for working with ANS.1 objects + +#ifndef CRYPTOPP_ASN_H +#define CRYPTOPP_ASN_H + +#include "cryptlib.h" +#include "filters.h" +#include "smartptr.h" +#include "stdcpp.h" +#include "queue.h" +#include "misc.h" + +#include + +// Issue 340 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief ASN.1 types +/// \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, + /// \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 flags are not complete +enum ASNIdFlag +{ + /// \brief ASN.1 Universal class + UNIVERSAL = 0x00, + // 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 +}; + +/// \brief Raises a BERDecodeErr +inline void BERDecodeError() {throw BERDecodeErr();} + +/// \brief Exception thrown when an unknown object identifier is encountered +class CRYPTOPP_DLL UnknownOID : public BERDecodeErr +{ +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 exception + UnknownOID(const char *err) : BERDecodeErr(err) {} +}; + +/// \brief DER encode a length +/// \param bt BufferedTransformation object for writing +/// \param length the size to encode +/// \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 +/// \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); + +/// \brief DER encode NULL +/// \param bt BufferedTransformation object for writing +CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &bt); + +/// \brief BER decode NULL +/// \param bt BufferedTransformation object for reading +CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &bt); + +/// \brief DER encode octet string +/// \param bt BufferedTransformation object for writing +/// \param str the string to encode +/// \param strLen the length of the string +/// \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 +/// \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 +/// \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 +/// \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 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 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 +/// \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 str is one octet with a value=0xa0 and unusedBits=5. The +/// value 0xa0 is 101b << 5. +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 str is one octet with a value=0xa0 and unusedBits=5. The +/// value 0xa0 is 101b << 5. +CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits); + +/// \brief BER decode and DER re-encode +/// \param bt BufferedTransformation object for writing +/// \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 +{ +public: + virtual ~OID() {} + + /// \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); + } + + /// \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; + } + + /// \brief DER encode this OID + /// \param bt BufferedTransformation object + void DEREncode(BufferedTransformation &bt) const; + + /// \brief BER decode an OID + /// \param bt BufferedTransformation object + void BERDecode(BufferedTransformation &bt); + + /// \brief BER decode an OID + /// \param bt BufferedTransformation object + /// \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. + ///
+	///   BERSequenceDecoder key(bt);
+	///   ...
+	///   BERSequenceDecoder algorithm(key);
+	///   GetAlgorithmID().BERDecodeAndCheck(algorithm);
+	/// 
+ 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& 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); + friend bool operator>=(const OID &lhs, const OID &rhs); + + std::vector m_values; + +private: + static void EncodeValue(BufferedTransformation &bt, word32 v); + static size_t DecodeValue(BufferedTransformation &bt, word32 &v); +}; + +/// \brief ASN.1 encoded object filter +class EncodedObjectFilter : public Filter +{ +public: + enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8}; + enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state; + + virtual ~EncodedObjectFilter() {} + + /// \brief Construct an EncodedObjectFilter + /// \param attachment a BufferedTrasformation to attach to this object + /// \param nObjects the number of objects + /// \param flags bitwise OR of EncodedObjectFilter::Flag + EncodedObjectFilter(BufferedTransformation *attachment = NULLPTR, unsigned int nObjects = 1, word32 flags = 0); + + /// \brief Input a byte buffer for processing + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + void Put(const byte *inString, size_t length); + + unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;} + unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];} + +private: + BufferedTransformation & CurrentTarget(); + + ByteQueue m_queue; + std::vector m_positions; + lword m_lengthRemaining; + word32 m_nObjects, m_nCurrentObject, m_level, m_flags; + byte m_id; +}; + +/// \brief BER General Decoder +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); + + /// \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; + + /// \brief Signals the end of messages to the object + /// \details Call this to denote end of sequence + void MessageEnd(); + +protected: + BufferedTransformation &m_inQueue; + lword m_length; + bool m_finished, m_definiteLength; + +private: + void Init(byte asnTag); + void StoreInitialize(const NameValuePairs ¶meters) + {CRYPTOPP_UNUSED(parameters); CRYPTOPP_ASSERT(false);} + lword ReduceLength(lword delta); +}; + +/// \brief DER General Encoder +class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue +{ +public: + /// \brief Default ASN.1 tag + enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)}; + + virtual ~DERGeneralEncoder(); + + /// \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); + + /// \brief Signals the end of messages to the object + /// \details Call this to denote end of sequence + void MessageEnd(); + +private: + BufferedTransformation &m_outQueue; + byte m_asnTag; + bool m_finished; +}; + +/// \brief BER Sequence Decoder +class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder +{ +public: + /// \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) {} + + /// \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) {} +}; + +/// \brief DER Sequence Encoder +class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder +{ +public: + /// \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) {} + + /// \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) {} +}; + +/// \brief BER Set Decoder +class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder +{ +public: + /// \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) {} + + /// \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) {} +}; + +/// \brief DER Set Encoder +class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder +{ +public: + /// \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) {} + + /// \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) {} +}; + +/// \brief Optional data encoder and decoder +/// \tparam T class or type +template +class ASNOptional : public member_ptr +{ +public: + /// \brief BER decode optional data + /// \param seqDecoder sequence with the optional ASN.1 data + /// \param tag ASN.1 tag to match as optional data + /// \param mask the mask to apply when matching the tag + /// \sa ASNTag and ASNIdFlag + void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED) + { + byte b; + if (seqDecoder.Peek(b) && (b & mask) == tag) + reset(new T(seqDecoder)); + } + + /// \brief DER encode optional data + /// \param out BufferedTransformation object + void DEREncode(BufferedTransformation &out) + { + if (this->get() != NULLPTR) + this->get()->DEREncode(out); + } +}; + +/// \brief Encode and decode ASN.1 objects with additional information +/// \tparam BASE base class or type +/// \details Encodes and decodes public keys, private keys and group +/// parameters with OID identifying the algorithm or scheme. +template +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE +{ +public: + /// \brief DER encode ASN.1 object + /// \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 + /// subjectPublicKeyInfo and privateKeyInfo parts. + void Save(BufferedTransformation &bt) const + {BEREncode(bt);} + + /// \brief BER decode ASN.1 object + /// \param bt BufferedTransformation object + void Load(BufferedTransformation &bt) + {BERDecode(bt);} +}; + +/// \brief Encodes and decodes subjectPublicKeyInfo +class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial +{ +public: + virtual ~X509PublicKey() {} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + /// \brief Retrieves the OID of the algorithm + /// \return OID of the algorithm + virtual OID GetAlgorithmID() const =0; + + /// \brief Decode algorithm parameters + /// \param bt BufferedTransformation object + /// \sa BERDecodePublicKey, RFC + /// 2459, section 7.3.1 + virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) + {BERDecodeNull(bt); return false;} + + /// \brief Encode algorithm parameters + /// \param bt BufferedTransformation object + /// \sa DEREncodePublicKey, RFC + /// 2459, section 7.3.1 + virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const + {DEREncodeNull(bt); return false;} + + /// \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 parametersPresent = true then BERDecodePublicKey() calls + /// BERDecodeAlgorithmParameters() to parse algorithm parameters. + /// \sa BERDecodeAlgorithmParameters + virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; + + /// \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 Decodes privateKeyInfo +class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial +{ +public: + virtual ~PKCS8PrivateKey() {} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + /// \brief Retrieves the OID of the algorithm + /// \return OID of the algorithm + virtual OID GetAlgorithmID() const =0; + + /// \brief Decode optional parameters + /// \param bt BufferedTransformation object + /// \sa BERDecodePrivateKey, RFC + /// 2459, section 7.3.1 + virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) + {BERDecodeNull(bt); return false;} + + /// \brief Encode optional parameters + /// \param bt BufferedTransformation object + /// \sa DEREncodePrivateKey, RFC + /// 2459, section 7.3.1 + virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const + {DEREncodeNull(bt); return false;} + + /// \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 parametersPresent = true then BERDecodePrivateKey() calls + /// BERDecodeAlgorithmParameters() to parse algorithm parameters. + /// \sa BERDecodeAlgorithmParameters + virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; + + /// \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; + + /// \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); + + /// \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: + ByteQueue m_optionalAttributes; +}; + +// ******************************************************** + +/// \brief DER Encode unsigned value +/// \tparam T class or type +/// \param out BufferedTransformation object +/// \param w unsigned value to encode +/// \param asnTag the ASN.1 identifier +/// \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM +template +size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER) +{ + byte buf[sizeof(w)+1]; + unsigned int bc; + if (asnTag == BOOLEAN) + { + buf[sizeof(w)] = w ? 0xff : 0; + bc = 1; + } + else + { + buf[0] = 0; + for (unsigned int i=0; i> (sizeof(w)-1-i)*8); + bc = sizeof(w); + while (bc > 1 && buf[sizeof(w)+1-bc] == 0) + --bc; + if (buf[sizeof(w)+1-bc] & 0x80) + ++bc; + } + out.Put(asnTag); + size_t lengthBytes = DERLengthEncode(out, bc); + out.Put(buf+sizeof(w)+1-bc, bc); + return 1+lengthBytes+bc; +} + +/// \brief BER Decode unsigned value +/// \tparam T fundamental C++ type +/// \param in BufferedTransformation object +/// \param w the decoded value +/// \param asnTag the ASN.1 identifier +/// \param minValue the minimum expected value +/// \param maxValue the maximum expected value +/// \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 +void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER, + T minValue = 0, T maxValue = T(0xffffffff)) +{ + byte b; + if (!in.Get(b) || b != asnTag) + BERDecodeError(); + + size_t bc; + bool definite = BERLengthDecode(in, bc); + if (!definite) + BERDecodeError(); + if (bc > in.MaxRetrievable()) // Issue 346 + BERDecodeError(); + if (asnTag == BOOLEAN && bc != 1) // X.690, 8.2.1 + BERDecodeError(); + if ((asnTag == INTEGER || asnTag == ENUMERATED) && bc == 0) // X.690, 8.3.1 and 8.4 + BERDecodeError(); + + SecByteBlock buf(bc); + + if (bc != in.Get(buf, bc)) + BERDecodeError(); + + // This consumes leading 0 octets. According to X.690, 8.3.2, it could be non-conforming behavior. + // X.690, 8.3.2 says "the bits of the first octet and bit 8 of the second octet ... (a) shall + // not all be ones and (b) shall not all be zeros ... These rules ensure that an integer value + // is always encoded in the smallest possible number of octet". + // We invented AER (Alternate Encoding Rules), which is more relaxed than BER, CER, and DER. + const byte *ptr = buf; + while (bc > sizeof(w) && *ptr == 0) + { + bc--; + ptr++; + } + if (bc > sizeof(w)) + BERDecodeError(); + + w = 0; + for (unsigned int i=0; i maxValue) + BERDecodeError(); +} + +#ifdef CRYPTOPP_DOXYGEN_PROCESSING +/// \brief Compare two OIDs for equality +/// \param lhs the first OID +/// \param rhs the second OID +/// \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 +/// \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 +/// \return true if the first OID is less than the second OID, false otherwise +/// \details operator<() calls std::lexicographical_compare() on the 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 greater than 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 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); +#else +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 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=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) + {return ! (lhsThe EAX +/// Mode of Operation. The EAX paper suggested a basic API to help standardize AEAD +/// schemes in software and promote adoption of the modes. +/// \sa Authenticated +/// Encryption on the Crypto++ wiki. +/// \since Crypto++ 5.6.0 + +#ifndef CRYPTOPP_AUTHENC_H +#define CRYPTOPP_AUTHENC_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Base class for authenticated encryption modes of operation +/// \details AuthenticatedSymmetricCipherBase() serves as a base implementation for one direction +/// (encryption or decryption) of a stream cipher or block cipher mode with authentication. +/// \details Crypto++ provides four authenticated encryption modes of operation - CCM, EAX, GCM +/// and OCB mode. All modes derive from AuthenticatedSymmetricCipherBase() and the +/// motivation for the API, like calling AAD a "header", can be found in Bellare, +/// Rogaway and Wagner's The EAX +/// Mode of Operation. The EAX paper suggested a basic API to help standardize AEAD +/// schemes in software and promote adoption of the modes. +/// \sa Authenticated +/// Encryption on the Crypto++ wiki. +/// \since Crypto++ 5.6.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher +{ +public: + AuthenticatedSymmetricCipherBase() : m_totalHeaderLength(0), m_totalMessageLength(0), + m_totalFooterLength(0), m_bufferedDataLength(0), m_state(State_Start) {} + + // StreamTransformation interface + bool IsRandomAccess() const {return false;} + bool IsSelfInverting() const {return true;} + + void SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;} + void Resynchronize(const byte *iv, int length=-1); + void Update(const byte *input, size_t length); + void ProcessData(byte *outString, const byte *inString, size_t length); + void TruncatedFinal(byte *mac, size_t macSize); + +protected: + void UncheckedSetKey(const byte * key, unsigned int length,const CryptoPP::NameValuePairs ¶ms) + {CRYPTOPP_UNUSED(key), CRYPTOPP_UNUSED(length), CRYPTOPP_UNUSED(params); CRYPTOPP_ASSERT(false);} + + void AuthenticateData(const byte *data, size_t len); + const SymmetricCipher & GetSymmetricCipher() const + {return const_cast(this)->AccessSymmetricCipher();} + + virtual SymmetricCipher & AccessSymmetricCipher() =0; + virtual bool AuthenticationIsOnPlaintext() const =0; + virtual unsigned int AuthenticationBlockSize() const =0; + virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) =0; + virtual void Resync(const byte *iv, size_t len) =0; + virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0; + virtual void AuthenticateLastHeaderBlock() =0; + virtual void AuthenticateLastConfidentialBlock() {} + virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0; + + // State_AuthUntransformed: authentication is applied to plain text (Authenticate-then-Encrypt) + // State_AuthTransformed: authentication is applied to cipher text (Encrypt-then-Authenticate) + enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter}; + + AlignedSecByteBlock m_buffer; + lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength; + unsigned int m_bufferedDataLength; + State m_state; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/base32.h b/third_party/cryptoppwin/include/cryptopp/base32.h new file mode 100644 index 00000000..80a64ed8 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/base32.h @@ -0,0 +1,158 @@ +// base32.h - written and placed in the public domain by Frank Palazzolo, based on hex.cpp by Wei Dai +// extended hex alphabet added by JW in November, 2017. + +/// \file base32.h +/// \brief Classes for Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder + +#ifndef CRYPTOPP_BASE32_H +#define CRYPTOPP_BASE32_H + +#include "cryptlib.h" +#include "basecode.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Base32 encodes data using DUDE encoding +/// \details Converts data to base32 using DUDE encoding. The default code is based on Differential Unicode Domain Encoding (DUDE) (draft-ietf-idn-dude-02.txt). +/// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder +class Base32Encoder : public SimpleProxyFilter +{ +public: + /// \brief Construct a Base32Encoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \param uppercase a flag indicating uppercase output + /// \param groupSize the size of the grouping + /// \param separator the separator to use between groups + /// \param terminator the terminator appeand after processing + /// \details Base32Encoder() constructs a default encoder. The constructor lacks fields for padding and + /// line breaks. You must use IsolatedInitialize() to change the default padding character or suppress it. + /// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder + Base32Encoder(BufferedTransformation *attachment = NULLPTR, bool uppercase = true, int groupSize = 0, const std::string &separator = ":", const std::string &terminator = "") + : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) + { + IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), groupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator))); + } + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + /// \details The following code modifies the padding and line break parameters for an encoder: + ///
+	///     Base32Encoder encoder;
+	///     AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
+	///     encoder.IsolatedInitialize(params);
+ /// \details You can change the encoding to RFC 4648, Base + /// 32 Encoding with Extended Hex Alphabet by performing the following: + ///
+	///     Base32Encoder encoder;
+	///     const byte ALPHABET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
+	///     AlgorithmParameters params = MakeParameters(Name::EncodingLookupArray(),(const byte *)ALPHABET);
+	///     encoder.IsolatedInitialize(params);
+ /// \details If you change the encoding alphabet, then you will need to change the decoding alphabet \a and + /// the decoder's lookup table. + /// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder + void IsolatedInitialize(const NameValuePairs ¶meters); +}; + +/// \brief Base32 decodes data using DUDE encoding +/// \details Converts data from base32 using DUDE encoding. The default code is based on Differential Unicode Domain Encoding (DUDE) (draft-ietf-idn-dude-02.txt). +/// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder +class Base32Decoder : public BaseN_Decoder +{ +public: + /// \brief Construct a Base32Decoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \sa IsolatedInitialize() for an example of modifying a Base32Decoder after construction. + Base32Decoder(BufferedTransformation *attachment = NULLPTR) + : BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {} + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + /// \details You can change the encoding to RFC 4648, Base + /// 32 Encoding with Extended Hex Alphabet by performing the following: + ///
+	///     int lookup[256];
+	///     const byte ALPHABET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
+	///     Base32Decoder::InitializeDecodingLookupArray(lookup, ALPHABET, 32, true /*insensitive*/);
+	///
+	///     Base32Decoder decoder;
+	///     AlgorithmParameters params = MakeParameters(Name::DecodingLookupArray(),(const int *)lookup);
+	///     decoder.IsolatedInitialize(params);
+ /// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder + void IsolatedInitialize(const NameValuePairs ¶meters); + +private: + /// \brief Provides the default decoding lookup table + /// \return default decoding lookup table + static const int * CRYPTOPP_API GetDefaultDecodingLookupArray(); +}; + +/// \brief Base32 encodes data using extended hex +/// \details Converts data to base32 using extended hex alphabet. The alphabet is different than Base32Encoder. +/// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder, RFC 4648, Base 32 Encoding with Extended Hex Alphabet. +/// \since Crypto++ 6.0 +class Base32HexEncoder : public SimpleProxyFilter +{ +public: + /// \brief Construct a Base32HexEncoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \param uppercase a flag indicating uppercase output + /// \param groupSize the size of the grouping + /// \param separator the separator to use between groups + /// \param terminator the terminator appeand after processing + /// \details Base32HexEncoder() constructs a default encoder. The constructor lacks fields for padding and + /// line breaks. You must use IsolatedInitialize() to change the default padding character or suppress it. + /// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder + Base32HexEncoder(BufferedTransformation *attachment = NULLPTR, bool uppercase = true, int groupSize = 0, const std::string &separator = ":", const std::string &terminator = "") + : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) + { + IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), groupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator))); + } + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + /// \details The following code modifies the padding and line break parameters for an encoder: + ///
+	///     Base32HexEncoder encoder;
+	///     AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
+	///     encoder.IsolatedInitialize(params);
+ void IsolatedInitialize(const NameValuePairs ¶meters); +}; + +/// \brief Base32 decodes data using extended hex +/// \details Converts data from base32 using extended hex alphabet. The alphabet is different than Base32Decoder. +/// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder, RFC 4648, Base 32 Encoding with Extended Hex Alphabet. +/// \since Crypto++ 6.0 +class Base32HexDecoder : public BaseN_Decoder +{ +public: + /// \brief Construct a Base32HexDecoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \sa Base32Encoder, Base32Decoder, Base32HexEncoder and Base32HexDecoder + Base32HexDecoder(BufferedTransformation *attachment = NULLPTR) + : BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {} + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + void IsolatedInitialize(const NameValuePairs ¶meters); + +private: + /// \brief Provides the default decoding lookup table + /// \return default decoding lookup table + static const int * CRYPTOPP_API GetDefaultDecodingLookupArray(); +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/base64.h b/third_party/cryptoppwin/include/cryptopp/base64.h new file mode 100644 index 00000000..be5c6b77 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/base64.h @@ -0,0 +1,158 @@ +// base64.h - originally written and placed in the public domain by Wei Dai + +/// \file base64.h +/// \brief Classes for the Base64Encoder, Base64Decoder, Base64URLEncoder and Base64URLDecoder + +#ifndef CRYPTOPP_BASE64_H +#define CRYPTOPP_BASE64_H + +#include "cryptlib.h" +#include "basecode.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Base64 encodes data using DUDE +/// \details Base64 encodes data per RFC 4648, Base 64 Encoding. +class Base64Encoder : public SimpleProxyFilter +{ +public: + /// \brief Construct a Base64Encoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \param insertLineBreaks a BufferedTrasformation to attach to this object + /// \param maxLineLength the length of a line if line breaks are used + /// \details Base64Encoder constructs a default encoder. The constructor lacks a parameter for padding, and you must + /// use IsolatedInitialize() to modify the Base64Encoder after construction. + /// \sa IsolatedInitialize() for an example of modifying an encoder after construction. + Base64Encoder(BufferedTransformation *attachment = NULLPTR, bool insertLineBreaks = true, int maxLineLength = 72) + : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) + { + IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength)); + } + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + /// \details The following code modifies the padding and line break parameters for an encoder: + ///
+	///     Base64Encoder encoder;
+	///     AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
+	///     encoder.IsolatedInitialize(params);
+ /// \details You can change the encoding to RFC 4648 web safe alphabet by performing the following: + ///
+	///     Base64Encoder encoder;
+	///     const byte ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+	///     AlgorithmParameters params = MakeParameters(Name::EncodingLookupArray(),(const byte *)ALPHABET);
+	///     encoder.IsolatedInitialize(params);
+ /// \details If you change the encoding alphabet, then you will need to change the decoding alphabet \a and + /// the decoder's lookup table. + /// \sa Base64URLEncoder for an encoder that provides the web safe alphabet, and Base64Decoder::IsolatedInitialize() + /// for an example of modifying a decoder's lookup table after construction. + void IsolatedInitialize(const NameValuePairs ¶meters); +}; + +/// \brief Base64 decodes data using DUDE +/// \details Base64 encodes data per RFC 4648, Base 64 Encoding. +class Base64Decoder : public BaseN_Decoder +{ +public: + /// \brief Construct a Base64Decoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \sa IsolatedInitialize() for an example of modifying an encoder after construction. + Base64Decoder(BufferedTransformation *attachment = NULLPTR) + : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {} + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + /// \details The default decoding alpahbet is RFC 4868. You can change the to RFC 4868 web safe alphabet + /// by performing the following: + ///
+	///     int lookup[256];
+	///     const byte ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+	///     Base64Decoder::InitializeDecodingLookupArray(lookup, ALPHABET, 64, false);
+	///
+	///     Base64Decoder decoder;
+	///     AlgorithmParameters params = MakeParameters(Name::DecodingLookupArray(),(const int *)lookup);
+	///     decoder.IsolatedInitialize(params);
+ /// \sa Base64URLDecoder for a decoder that provides the web safe alphabet, and Base64Encoder::IsolatedInitialize() + /// for an example of modifying an encoder's alphabet after construction. + void IsolatedInitialize(const NameValuePairs ¶meters); + +private: + /// \brief Provides the default decoding lookup table + /// \return default decoding lookup table + static const int * CRYPTOPP_API GetDecodingLookupArray(); +}; + +/// \brief Base64 encodes data using a web safe alphabet +/// \details Base64 encodes data per RFC 4648, Base 64 Encoding +/// with URL and Filename Safe Alphabet. +class Base64URLEncoder : public SimpleProxyFilter +{ +public: + /// \brief Construct a Base64URLEncoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \param insertLineBreaks a BufferedTrasformation to attach to this object + /// \param maxLineLength the length of a line if line breaks are used + /// \details Base64URLEncoder() constructs a default encoder using a web safe alphabet. The constructor ignores + /// insertLineBreaks and maxLineLength because the web and URL safe specifications don't use them. They are + /// present in the constructor for API compatibility with Base64Encoder so it is a drop-in replacement. The + /// constructor also disables padding on the encoder for the same reason. + /// \details If you need line breaks or padding, then you must use IsolatedInitialize() to set them + /// after constructing a Base64URLEncoder. + /// \sa Base64Encoder for an encoder that provides a classic alphabet, and Base64URLEncoder::IsolatedInitialize + /// for an example of modifying an encoder after construction. + Base64URLEncoder(BufferedTransformation *attachment = NULLPTR, bool insertLineBreaks = false, int maxLineLength = -1) + : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) + { + CRYPTOPP_UNUSED(insertLineBreaks), CRYPTOPP_UNUSED(maxLineLength); + IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), false)(Name::MaxLineLength(), -1)(Name::Pad(),false)); + } + + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached + /// transformations. If initialization should be propagated, then use the Initialize() function. + /// \details The following code modifies the padding and line break parameters for an encoder: + ///
+	///     Base64URLEncoder encoder;
+	///     AlgorithmParameters params = MakeParameters(Name::Pad(), true)(Name::InsertLineBreaks(), true);
+	///     encoder.IsolatedInitialize(params);
+ /// \sa Base64Encoder for an encoder that provides a classic alphabet. + void IsolatedInitialize(const NameValuePairs ¶meters); +}; + +/// \brief Base64 decodes data using a web safe alphabet +/// \details Base64 encodes data per RFC 4648, Base 64 Encoding +/// with URL and Filename Safe Alphabet. +class Base64URLDecoder : public BaseN_Decoder +{ +public: + /// \brief Construct a Base64URLDecoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \details Base64URLDecoder() constructs a default decoder using a web safe alphabet. + /// \sa Base64Decoder for a decoder that provides a classic alphabet. + Base64URLDecoder(BufferedTransformation *attachment = NULLPTR) + : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {} + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs used to initialize this object + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on + /// attached transformations. If initialization should be propagated, then use the Initialize() function. + /// \sa Base64Decoder for a decoder that provides a classic alphabet, and Base64URLEncoder::IsolatedInitialize + /// for an example of modifying an encoder after construction. + void IsolatedInitialize(const NameValuePairs ¶meters); + +private: + /// \brief Provides the default decoding lookup table + /// \return default decoding lookup table + static const int * CRYPTOPP_API GetDecodingLookupArray(); +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/basecode.h b/third_party/cryptoppwin/include/cryptopp/basecode.h new file mode 100644 index 00000000..7158de6a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/basecode.h @@ -0,0 +1,146 @@ +// basecode.h - originally written and placed in the public domain by Wei Dai + +/// \file +/// \brief Base classes for working with encoders and decoders. + +#ifndef CRYPTOPP_BASECODE_H +#define CRYPTOPP_BASECODE_H + +#include "cryptlib.h" +#include "filters.h" +#include "algparam.h" +#include "argnames.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Encoder for bases that are a power of 2 +class CRYPTOPP_DLL BaseN_Encoder : public Unflushable +{ +public: + /// \brief Construct a BaseN_Encoder + /// \param attachment a BufferedTransformation to attach to this object + BaseN_Encoder(BufferedTransformation *attachment=NULLPTR) + : m_alphabet(NULLPTR), m_padding(0), m_bitsPerChar(0) + , m_outputBlockSize(0), m_bytePos(0), m_bitPos(0) + {Detach(attachment);} + + /// \brief Construct a BaseN_Encoder + /// \param alphabet table of ASCII characters to use as the alphabet + /// \param log2base the log2base + /// \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 + /// \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); + BaseN_Encoder::IsolatedInitialize( + MakeParameters + (Name::EncodingLookupArray(), alphabet) + (Name::Log2Base(), log2base) + (Name::Pad(), padding != -1) + (Name::PaddingByte(), byte(padding))); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + const byte *m_alphabet; + int m_padding, m_bitsPerChar, m_outputBlockSize; + int m_bytePos, m_bitPos; + SecByteBlock m_outBuf; +}; + +/// \brief Decoder for bases that are a power of 2 +class CRYPTOPP_DLL BaseN_Decoder : public Unflushable +{ +public: + /// \brief Construct a BaseN_Decoder + /// \param attachment a BufferedTransformation to attach to this object + /// \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_bitsPerChar(0) + , m_outputBlockSize(0), m_bytePos(0), m_bitPos(0) + {Detach(attachment);} + + /// \brief Construct a BaseN_Decoder + /// \param lookup table of values + /// \param log2base the log2base + /// \param attachment a BufferedTransformation to attach to this object + /// \details log2base is the exponent (like 5 in 25), and not + /// the number of elements (like 32). + /// \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_bitsPerChar(0) + , m_outputBlockSize(0), m_bytePos(0), m_bitPos(0) + { + Detach(attachment); + BaseN_Decoder::IsolatedInitialize( + MakeParameters + (Name::DecodingLookupArray(), lookup) + (Name::Log2Base(), log2base)); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + + /// \brief Initializes BaseN lookup array + /// \param lookup table of values + /// \param alphabet table of ASCII characters + /// \param base the base for the encoder + /// \param caseInsensitive flag indicating whether the alphabet is case sensitivie + /// \pre COUNTOF(lookup) == 256 + /// \pre COUNTOF(alphabet) == base + /// \details Internally, the function sets the first 256 elements in the lookup table to + /// their value from the alphabet array or -1. base is the number of element (like 32), + /// and not an exponent (like 5 in 25) + static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive); + +private: + const int *m_lookup; + int m_bitsPerChar, m_outputBlockSize; + int m_bytePos, m_bitPos; + SecByteBlock m_outBuf; +}; + +/// \brief Filter that breaks input stream into groups of fixed size +class CRYPTOPP_DLL Grouper : public Bufferless +{ +public: + /// \brief Construct a Grouper + /// \param attachment a BufferedTransformation to attach to this object + Grouper(BufferedTransformation *attachment=NULLPTR) + : m_groupSize(0), m_counter(0) {Detach(attachment);} + + /// \brief Construct a Grouper + /// \param groupSize the size of the grouping + /// \param separator the separator to use between groups + /// \param terminator the terminator appeand after processing + /// \param attachment a BufferedTransformation to attach to this object + Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULLPTR) + : m_groupSize(0), m_counter(0) + { + Detach(attachment); + Grouper::IsolatedInitialize( + MakeParameters + (Name::GroupSize(), groupSize) + (Name::Separator(), ConstByteArrayParameter(separator)) + (Name::Terminator(), ConstByteArrayParameter(terminator))); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + SecByteBlock m_separator, m_terminator; + size_t m_groupSize, m_counter; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/bench.h b/third_party/cryptoppwin/include/cryptopp/bench.h new file mode 100644 index 00000000..561b6578 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/bench.h @@ -0,0 +1,105 @@ +// bench.h - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#ifndef CRYPTOPP_BENCH_H +#define CRYPTOPP_BENCH_H + +#include "cryptlib.h" + +#include +#include +#include +#include + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +// More granular control over benchmarks +enum TestClass { + /// \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, + PublicKeyEC=PublicKeyAgreementEC|PublicKeyEncryptionEC|PublicKeySignatureEC|PublicKeyOtherEC, + + All=Unkeyed|SharedKey|PublicKey|PublicKeyEC, + + TestFirst=(0), TestLast=(1<<15) +}; + +extern const double CLOCK_TICKS_PER_SECOND; +extern double g_allocatedTime; +extern double g_hertz; +extern double g_logTotal; +extern unsigned int g_logCount; +extern const byte defaultKey[]; + +// Test book keeping +extern time_t g_testBegin; +extern time_t g_testEnd; + +// 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 BenchmarkUnkeyedAlgorithms(double t, double hertz); +// Shared key systems +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); + +// These are defined in bench2.cpp +extern void BenchMarkKeying(SimpleKeyingInterface &c, size_t keyLength, const NameValuePairs ¶ms); +extern void BenchMark(const char *name, AuthenticatedSymmetricCipher &cipher, double timeTotal); + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/blake2.h b/third_party/cryptoppwin/include/cryptopp/blake2.h new file mode 100644 index 00000000..bbbe134b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/blake2.h @@ -0,0 +1,444 @@ +// 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 +/// \details This implementation follows Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's +/// BLAKE2: simpler, smaller, fast as MD5 (2013.01.29). +/// Static algorithm name return either "BLAKE2b" or "BLAKE2s". An object algorithm name follows +/// the naming described in RFC 7693, The +/// BLAKE2 Cryptographic Hash and Message Authentication Code (MAC). +/// \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 + +#include "cryptlib.h" +#include "secblock.h" +#include "seckey.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief BLAKE2s hash information +/// \since Crypto++ 5.6.4 +struct BLAKE2s_Info : public VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> +{ + 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 = 64); + CRYPTOPP_CONSTANT(DIGESTSIZE = 32); + CRYPTOPP_CONSTANT(SALTSIZE = 8); + CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 8); + + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";} +}; + +/// \brief BLAKE2b hash information +/// \since Crypto++ 5.6.4 +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 BLAKE2s parameter block +struct CRYPTOPP_NO_VTABLE BLAKE2s_ParameterBlock +{ + 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 m_data; +}; + +/// \brief BLAKE2b parameter block +struct CRYPTOPP_NO_VTABLE BLAKE2b_ParameterBlock +{ + 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 m_data; +}; + +/// \brief BLAKE2s state information +/// \since Crypto++ 5.6.4 +struct CRYPTOPP_NO_VTABLE BLAKE2s_State +{ + 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 m_hft; + FixedSizeAlignedSecBlock m_buf; + size_t m_len; +}; + +/// \brief BLAKE2b state information +/// \since Crypto++ 5.6.4 +struct CRYPTOPP_NO_VTABLE BLAKE2b_State +{ + BLAKE2b_State() { + Reset(); + } + + void Reset(); + + inline word64* h() { + return m_hft.data(); + } + + inline word64* t() { + return m_hft.data() + 8; + } + + 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 m_hft; + FixedSizeAlignedSecBlock m_buf; + size_t m_len; +}; + +/// \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 +/// BLAKE2: simpler, smaller, fast as MD5 (2013.01.29). +/// \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 +{ +public: + 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 + /// RFC 7693, The BLAKE2 Cryptographic Hash and + /// Message Authentication Code (MAC). 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 treeMode=false (default), then State::f[1] is never set. If + /// treeMode=true, 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 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 +/// BLAKE2: simpler, smaller, fast as MD5 (2013.01.29). +/// \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 +{ +public: + 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 + /// RFC 7693, The BLAKE2 Cryptographic Hash and + /// Message Authentication Code (MAC). 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 treeMode=false (default), then State::f[1] is never set. If + /// treeMode=true, 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 + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/blowfish.h b/third_party/cryptoppwin/include/cryptopp/blowfish.h new file mode 100644 index 00000000..8032491e --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/blowfish.h @@ -0,0 +1,54 @@ +// blowfish.h - originally written and placed in the public domain by Wei Dai + +/// \file blowfish.h +/// \brief Classes for the Blowfish block cipher + +#ifndef CRYPTOPP_BLOWFISH_H +#define CRYPTOPP_BLOWFISH_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Blowfish block cipher information +struct Blowfish_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 4, 56>, public FixedRounds<16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Blowfish";} +}; + +// Blowfish + +/// \brief Blowfish block cipher +/// \since Crypto++ 1.0 +class Blowfish : public Blowfish_Info, public BlockCipherDocumentation +{ + /// \brief Class specific implementation and overrides used to operate the cipher. + /// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + void UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs ¶ms); + + private: + void crypt_block(const word32 in[2], word32 out[2]) const; + + static const word32 p_init[ROUNDS+2]; + static const word32 s_init[4*256]; + + FixedSizeSecBlock pbox; + FixedSizeSecBlock sbox; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Blowfish::Encryption BlowfishEncryption; +typedef Blowfish::Decryption BlowfishDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/blumshub.h b/third_party/cryptoppwin/include/cryptopp/blumshub.h new file mode 100644 index 00000000..997a5152 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/blumshub.h @@ -0,0 +1,70 @@ +// blumshub.h - originally written and placed in the public domain by Wei Dai + +/// \file blumshub.h +/// \brief Classes for Blum Blum Shub generator + +#ifndef CRYPTOPP_BLUMSHUB_H +#define CRYPTOPP_BLUMSHUB_H + +#include "cryptlib.h" +#include "modarith.h" +#include "integer.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \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(); + byte GenerateByte(); + void GenerateBlock(byte *output, size_t size); + void ProcessData(byte *outString, const byte *inString, size_t length); + + bool IsSelfInverting() const {return true;} + bool IsForwardTransformation() const {return true;} + +protected: + ModularArithmetic modn; + Integer current; + word maxBits, bitsLeft; +}; + +/// \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() {} + + /// \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;} + void Seek(lword index); + +protected: + const Integer p, q; + const Integer x0; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/camellia.h b/third_party/cryptoppwin/include/cryptopp/camellia.h new file mode 100644 index 00000000..2d551dcd --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/camellia.h @@ -0,0 +1,49 @@ +// camellia.h - originally written and placed in the public domain by Wei Dai + +/// \file camellia.h +/// \brief Classes for the Camellia block cipher + +#ifndef CRYPTOPP_CAMELLIA_H +#define CRYPTOPP_CAMELLIA_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Camellia block cipher information +struct Camellia_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Camellia";} +}; + +/// \brief Camellia block cipher +/// \sa Camellia +class Camellia : public Camellia_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + CRYPTOPP_ALIGN_DATA(4) static const byte s1[256]; + static const word32 SP[4][256]; + + unsigned int m_rounds; + SecBlock m_key; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Camellia::Encryption CamelliaEncryption; +typedef Camellia::Decryption CamelliaDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/cast.h b/third_party/cryptoppwin/include/cryptopp/cast.h new file mode 100644 index 00000000..424cf62b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/cast.h @@ -0,0 +1,109 @@ +// cast.h - originally written and placed in the public domain by Wei Dai + +/// \file cast.h +/// \brief Classes for the CAST-128 and CAST-256 block ciphers +/// \since Crypto++ 2.2 + +#ifndef CRYPTOPP_CAST_H +#define CRYPTOPP_CAST_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief CAST block cipher base +/// \since Crypto++ 2.2 +class CAST +{ +protected: + static const word32 S[8][256]; +}; + +/// \brief CAST128 block cipher information +/// \since Crypto++ 2.2 +struct CAST128_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 5, 16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "CAST-128";} +}; + +/// \brief CAST128 block cipher +/// \sa CAST-128 +/// \since Crypto++ 2.2 +class CAST128 : public CAST128_Info, public BlockCipherDocumentation +{ + /// \brief CAST128 block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public CAST, public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + bool reduced; + FixedSizeSecBlock K; + mutable FixedSizeSecBlock m_t; + }; + + /// \brief CAST128 block cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief CAST128 block cipher decryption operation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief CAST256 block cipher information +/// \since Crypto++ 4.0 +struct CAST256_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 4> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "CAST-256";} +}; + +/// \brief CAST256 block cipher +/// \sa CAST-256 +/// \since Crypto++ 4.0 +class CAST256 : public CAST256_Info, public BlockCipherDocumentation +{ + /// \brief CAST256 block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public CAST, public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + static const word32 t_m[8][24]; + static const unsigned int t_r[8][24]; + + static void Omega(int i, word32 kappa[8]); + + FixedSizeSecBlock K; + mutable FixedSizeSecBlock kappa; + mutable FixedSizeSecBlock m_t; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef CAST128::Encryption CAST128Encryption; +typedef CAST128::Decryption CAST128Decryption; + +typedef CAST256::Encryption CAST256Encryption; +typedef CAST256::Decryption CAST256Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/cbcmac.h b/third_party/cryptoppwin/include/cryptopp/cbcmac.h new file mode 100644 index 00000000..5a0c1201 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/cbcmac.h @@ -0,0 +1,63 @@ +// cbcmac.h - originally written and placed in the public domain by Wei Dai + +/// \file +/// \brief Classes for CBC MAC +/// \since Crypto++ 3.1 + +#ifndef CRYPTOPP_CBCMAC_H +#define CRYPTOPP_CBCMAC_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief CBC-MAC base class +/// \since Crypto++ 3.1 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode +{ +public: + CBC_MAC_Base() : m_counter(0) {} + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int DigestSize() const {return const_cast(this)->AccessCipher().BlockSize();} + +protected: + virtual BlockCipher & AccessCipher() =0; + +private: + void ProcessBuf(); + SecByteBlock m_reg; + unsigned int m_counter; +}; + +/// \brief CBC-MAC +/// \tparam T BlockCipherDocumentation derived class +/// \details CBC-MAC is compatible with FIPS 113. The MAC is secure only for fixed +/// length messages. For variable length messages use CMAC or DMAC. +/// \sa CBC-MAC +/// \since Crypto++ 3.1 +template +class CBC_MAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs +{ +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::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} + + static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";} + +private: + BlockCipher & AccessCipher() {return m_cipher;} + typename T::Encryption m_cipher; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ccm.h b/third_party/cryptoppwin/include/cryptopp/ccm.h new file mode 100644 index 00000000..f4f8ab05 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ccm.h @@ -0,0 +1,123 @@ +// ccm.h - originally written and placed in the public domain by Wei Dai + +/// \file ccm.h +/// \brief CCM block cipher mode of operation +/// \since Crypto++ 5.6.0 + +#ifndef CRYPTOPP_CCM_H +#define CRYPTOPP_CCM_H + +#include "authenc.h" +#include "modes.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief CCM block cipher base implementation +/// \details Base implementation of the AuthenticatedSymmetricCipher interface +/// \since Crypto++ 5.6.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase +{ +public: + CCM_Base() + : m_digestSize(0), m_L(0), m_messageLength(0), m_aadLength(0) {} + + // 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 + {return GetBlockCipher().MaxKeyLength();} + size_t DefaultKeyLength() const + {return GetBlockCipher().DefaultKeyLength();} + size_t GetValidKeyLength(size_t keylength) const + {return GetBlockCipher().GetValidKeyLength(keylength);} + bool IsValidKeyLength(size_t keylength) const + {return GetBlockCipher().IsValidKeyLength(keylength);} + unsigned int OptimalDataAlignment() const + {return GetBlockCipher().OptimalDataAlignment();} + IV_Requirement IVRequirement() const + {return UNIQUE_IV;} + unsigned int IVSize() const + {return 8;} + unsigned int MinIVLength() const + {return 7;} + unsigned int MaxIVLength() const + {return 13;} + unsigned int DigestSize() const + {return m_digestSize;} + lword MaxHeaderLength() const + {return W64LIT(0)-1;} + lword MaxMessageLength() const + {return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;} + bool NeedsPrespecifiedDataLengths() const + {return true;} + void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength); + +protected: + // AuthenticatedSymmetricCipherBase + bool AuthenticationIsOnPlaintext() const + {return true;} + unsigned int AuthenticationBlockSize() const + {return GetBlockCipher().BlockSize();} + void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + 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); + SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} + + virtual BlockCipher & AccessBlockCipher() =0; + virtual int DefaultDigestSize() const =0; + + const BlockCipher & GetBlockCipher() const {return const_cast(this)->AccessBlockCipher();} + byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;} + + enum {REQUIRED_BLOCKSIZE = 16}; + int m_digestSize, m_L; + word64 m_messageLength, m_aadLength; + CTR_Mode_ExternalCipher::Encryption m_ctr; +}; + +/// \brief CCM block cipher final implementation +/// \tparam T_BlockCipher block cipher +/// \tparam T_DefaultDigestSize default digest size, in bytes +/// \tparam T_IsEncryption direction in which to operate the cipher +/// \since Crypto++ 5.6.0 +template +class CCM_Final : public CCM_Base +{ +public: + static std::string StaticAlgorithmName() + {return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");} + bool IsForwardTransformation() const + {return T_IsEncryption;} + +private: + BlockCipher & AccessBlockCipher() {return m_cipher;} + int DefaultDigestSize() const {return T_DefaultDigestSize;} + typename T_BlockCipher::Encryption m_cipher; +}; + +/// \brief CCM block cipher mode of operation +/// \tparam T_BlockCipher block cipher +/// \tparam T_DefaultDigestSize default digest size, in bytes +/// \details \p CCM provides the \p Encryption and \p Decryption typedef. See GCM_Base +/// and GCM_Final for the AuthenticatedSymmetricCipher implementation. +/// \sa CCM Mode and +/// Modes of Operation +/// on the Crypto++ wiki. +/// \since Crypto++ 5.6.0 +template +struct CCM : public AuthenticatedSymmetricCipherDocumentation +{ + typedef CCM_Final Encryption; + typedef CCM_Final Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/chacha.h b/third_party/cryptoppwin/include/cryptopp/chacha.h new file mode 100644 index 00000000..8b21ebb2 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/chacha.h @@ -0,0 +1,223 @@ +// chacha.h - written and placed in the public domain by Jeffrey Walton. +// 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 ChaCha, a +/// variant of Salsa20 (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 +/// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, +/// and TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. Finally, +/// the library provides XChaCha: +/// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03). +/// \since ChaCha since Crypto++ 5.6.4, ChaChaTLS and XChaCha20 since Crypto++ 8.1 + +#ifndef CRYPTOPP_CHACHA_H +#define CRYPTOPP_CHACHA_H + +#include "strciphr.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +////////////////////////////// Bernstein ChaCha ////////////////////////////// + +/// \brief ChaCha stream cipher information +/// \since Crypto++ 5.6.4 +struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8> +{ + /// \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 +class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy +{ +public: + virtual ~ChaCha_Policy() {} + ChaCha_Policy() : m_rounds(ROUNDS) {} + +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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; + + CRYPTOPP_CONSTANT(ROUNDS = 20); // Default rounds + FixedSizeAlignedSecBlock m_state; + unsigned int m_rounds; +}; + +/// \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 ChaCha, a variant +/// of Salsa20 (2008.01.28). +/// \since Crypto++ 5.6.4 +struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation +{ + /// \brief ChaCha Encryption + typedef SymmetricCipherFinal >, ChaCha_Info > Encryption; + /// \brief ChaCha Decryption + typedef Encryption Decryption; +}; + +////////////////////////////// IETF ChaChaTLS ////////////////////////////// + +/// \brief IETF ChaCha20 stream cipher information +/// \since Crypto++ 8.1 +struct ChaChaTLS_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 12>, FixedRounds<20> +{ + /// \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 IETF ChaCha20 stream cipher implementation +/// \since Crypto++ 8.1 +class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy +{ +public: + virtual ~ChaChaTLS_Policy() {} + ChaChaTLS_Policy() : m_counter(0) {} + +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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 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 +/// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, and +/// TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. +/// \sa RFC 8439, ChaCha20 and +/// Poly1305 for IETF Protocols, How +/// to handle block counter wrap in IETF's ChaCha algorithm? and +/// Issue +/// 790, ChaChaTLS results when counter block wraps. +/// \since Crypto++ 8.1 +struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation +{ + /// \brief ChaCha-TLS Encryption + typedef SymmetricCipherFinal >, 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 +{ +public: + virtual ~XChaCha20_Policy() {} + XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {} + +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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 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 XChaCha: +/// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03), How +/// to handle block counter wrap in IETF's ChaCha algorithm? and +/// Issue +/// 790, ChaCha20 results when counter block wraps. +/// \since Crypto++ 8.1 +struct XChaCha20 : public XChaCha20_Info, public SymmetricCipherDocumentation +{ + /// \brief XChaCha Encryption + typedef SymmetricCipherFinal >, XChaCha20_Info > Encryption; + /// \brief XChaCha Decryption + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_CHACHA_H diff --git a/third_party/cryptoppwin/include/cryptopp/chachapoly.h b/third_party/cryptoppwin/include/cryptopp/chachapoly.h new file mode 100644 index 00000000..27d4d593 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \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 macSize < TagSize(). + 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. + /// message 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 macLength < TagSize(). + 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 ¶ms); + 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 ¶ms); + + 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 RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \since Crypto++ 8.1 +template +class ChaCha20Poly1305_Final : public ChaCha20Poly1305_Base +{ +public: + virtual ~ChaCha20Poly1305_Final() {} + +protected: + const SymmetricCipher & GetSymmetricCipher() + {return const_cast(this)->AccessSymmetricCipher();} + SymmetricCipher & AccessSymmetricCipher() + {return m_cipher;} + bool IsForwardTransformation() const + {return T_IsEncryption;} + + const MessageAuthenticationCode & GetMAC() const + {return const_cast(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 RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \since Crypto++ 8.1 +struct ChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation +{ + /// \brief ChaCha20Poly1305 encryption + typedef ChaCha20Poly1305_Final Encryption; + /// \brief ChaCha20Poly1305 decryption + typedef ChaCha20Poly1305_Final 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 macSize < TagSize(). + 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. + /// message 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 macLength < TagSize(). + 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 ¶ms); + 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 ¶ms); + + 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 RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \since Crypto++ 8.1 +template +class XChaCha20Poly1305_Final : public XChaCha20Poly1305_Base +{ +public: + virtual ~XChaCha20Poly1305_Final() {} + +protected: + const SymmetricCipher & GetSymmetricCipher() + {return const_cast(this)->AccessSymmetricCipher();} + SymmetricCipher & AccessSymmetricCipher() + {return m_cipher;} + bool IsForwardTransformation() const + {return T_IsEncryption;} + + const MessageAuthenticationCode & GetMAC() const + {return const_cast(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 RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \since Crypto++ 8.1 +struct XChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation +{ + /// \brief XChaCha20Poly1305 encryption + typedef XChaCha20Poly1305_Final Encryption; + /// \brief XChaCha20Poly1305 decryption + typedef XChaCha20Poly1305_Final Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_CHACHA_POLY1305_H diff --git a/third_party/cryptoppwin/include/cryptopp/cham.h b/third_party/cryptoppwin/include/cryptopp/cham.h new file mode 100644 index 00000000..2ce7b8e6 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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, CHAM, +/// +/// CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices +/// \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 + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + + SecBlock m_rk; + mutable FixedSizeSecBlock 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; + /// \brief CHAM64 decryption + typedef BlockCipherFinal 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, CHAM, +/// +/// CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices +/// \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 + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + std::string AlgorithmProvider() const; + + SecBlock m_rk; + mutable FixedSizeSecBlock 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; + /// \brief CHAM128 decryption + typedef BlockCipherFinal Decryption; +}; + +/// \brief CHAM128 encryption +typedef CHAM128::Encryption CHAM128Encryption; +/// \brief CHAM128 decryption +typedef CHAM128::Decryption CHAM128Decryption; + +NAMESPACE_END + +#endif // CRYPTOPP_CHAM_H diff --git a/third_party/cryptoppwin/include/cryptopp/channels.h b/third_party/cryptoppwin/include/cryptopp/channels.h new file mode 100644 index 00000000..d7aecd2a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/channels.h @@ -0,0 +1,142 @@ +// channels.h - originally written and placed in the public domain by Wei Dai + +/// \file channels.h +/// \brief Classes for multiple named channels + +#ifndef CRYPTOPP_CHANNELS_H +#define CRYPTOPP_CHANNELS_H + +#include "cryptlib.h" +#include "simple.h" +#include "smartptr.h" +#include "stdcpp.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4355) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if 0 +/// Route input on default channel to different and/or multiple channels based on message sequence number +class MessageSwitch : public Sink +{ +public: + void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel); + void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel); + + void Put(byte inByte); + void Put(const byte *inString, unsigned int length); + + void Flush(bool completeFlush, int propagation=-1); + void MessageEnd(int propagation=-1); + void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1); + void MessageSeriesEnd(int propagation=-1); + +private: + typedef std::pair Route; + struct RangeRoute + { + RangeRoute(unsigned int begin, unsigned int end, const Route &route) + : begin(begin), end(end), route(route) {} + bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;} + unsigned int begin, end; + Route route; + }; + + typedef std::list RouteList; + typedef std::list DefaultRouteList; + + RouteList m_routes; + DefaultRouteList m_defaultRoutes; + unsigned int m_nCurrentMessage; +}; +#endif + +class ChannelSwitchTypedefs +{ +public: + typedef std::pair Route; + typedef std::multimap RouteMap; + + typedef std::pair > DefaultRoute; + typedef std::list DefaultRouteList; + + // SunCC workaround: can't use const_iterator here + typedef RouteMap::iterator MapIterator; + typedef DefaultRouteList::iterator ListIterator; +}; + +class ChannelSwitch; + +class ChannelRouteIterator : public ChannelSwitchTypedefs +{ +public: + ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs), m_useDefault(false) {} + + void Reset(const std::string &channel); + bool End() const; + void Next(); + BufferedTransformation & Destination(); + const std::string & Channel(); + + ChannelSwitch& m_cs; + std::string m_channel; + bool m_useDefault; + MapIterator m_itMapCurrent, m_itMapEnd; + ListIterator m_itListCurrent, m_itListEnd; + +protected: + // Hide this to see if we break something... + ChannelRouteIterator(); +}; + +/// Route input to different and/or multiple channels based on channel ID +class CRYPTOPP_DLL ChannelSwitch : public Multichannel, public ChannelSwitchTypedefs +{ +public: + ChannelSwitch() : m_it(*this), m_blocked(false) {} + ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false) + { + AddDefaultRoute(destination); + } + ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false) + { + AddDefaultRoute(destination, outChannel); + } + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + + 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); + + bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true); + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); + + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); + + void AddDefaultRoute(BufferedTransformation &destination); + void RemoveDefaultRoute(BufferedTransformation &destination); + void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel); + void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel); + void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); + void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); + +private: + RouteMap m_routeMap; + DefaultRouteList m_defaultRoutes; + + ChannelRouteIterator m_it; + bool m_blocked; + + friend class ChannelRouteIterator; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/cmac.h b/third_party/cryptoppwin/include/cryptopp/cmac.h new file mode 100644 index 00000000..91d9f7f9 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/cmac.h @@ -0,0 +1,76 @@ +// cmac.h - originally written and placed in the public domain by Wei Dai + +/// \file cmac.h +/// \brief Classes for CMAC message authentication code +/// \since Crypto++ 5.6.0 + +#ifndef CRYPTOPP_CMAC_H +#define CRYPTOPP_CMAC_H + +#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 +/// \since Crypto++ 5.6.0 +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 ¶ms); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + 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; + + const BlockCipher & GetCipher() const {return const_cast(this)->AccessCipher();} + virtual BlockCipher & AccessCipher() =0; + + void ProcessBuf(); + SecByteBlock m_reg; + unsigned int m_counter; +}; + +/// \brief CMAC message authentication code +/// \tparam T block cipher +/// \details Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32. +/// \sa CMAC +/// \since Crypto++ 5.6.0 +template +class CMAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs +{ +public: + /// \brief Construct a CMAC + CMAC() {} + /// \brief Construct a CMAC + /// \param key the MAC key + /// \param length the key size, in bytes + CMAC(const byte *key, size_t length=SameKeyLengthAs::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} + + static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";} + +private: + BlockCipher & AccessCipher() {return m_cipher;} + typename T::Encryption m_cipher; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/config.h b/third_party/cryptoppwin/include/cryptopp/config.h new file mode 100644 index 00000000..e96b1127 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/config.h @@ -0,0 +1,33 @@ +// config.h - originally written and placed in the public domain by Wei Dai + +/// \file config.h +/// \brief Library configuration file +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// on the Crypto++ wiki +/// \since Crypto++ 8.3 + +/// \file config.h +/// \brief Library configuration file + +#ifndef CRYPTOPP_CONFIG_H +#define 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_align.h b/third_party/cryptoppwin/include/cryptopp/config_align.h new file mode 100644 index 00000000..d6d85e75 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_align.h provides defines for aligned memory +/// allocations. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_align.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_asm.h b/third_party/cryptoppwin/include/cryptopp/config_asm.h new file mode 100644 index 00000000..edfbdefb --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_asm.h provides defines for instruction set +/// architectures +/// and inline assembly. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_asm.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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 code will +// not explicitly 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_asm.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 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 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_cpu.h b/third_party/cryptoppwin/include/cryptopp/config_cpu.h new file mode 100644 index 00000000..15f694e7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_cpu.h provides defines for the cpu and machine +/// architecture. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_cpu.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// on the Crypto++ wiki, +/// Sourceforge +/// Pre-defined Compiler Macros +/// \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 Debian X32 Port, + /// Gentoo + /// Multilib Concepts + #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 CentOS Issue + /// 14599: sysconf(_SC_LEVEL1_DCACHE_LINESIZE) returns 0 instead of 128 + /// \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 .data). 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 + /// _MSC_VER or __BORLANDC__ are defined. + #define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY ... + /// \brief GNU style inline assembly + /// \details CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY is defined when neither + /// _MSC_VER nor __BORLANDC__ are defined. + #define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY ... +#elif defined(CRYPTOPP_MSC_VERSION) || defined(__BORLANDC__) || \ + defined(CRYPTOPP_MSVC_CLANG_VERSION) + #define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 1 +#else + #define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY 1 +#endif + +#endif // CRYPTOPP_CONFIG_CPU_H diff --git a/third_party/cryptoppwin/include/cryptopp/config_cxx.h b/third_party/cryptoppwin/include/cryptopp/config_cxx.h new file mode 100644 index 00000000..ffd57add --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_cxx.h provides defines for C++ language and +/// runtime library +/// features. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_cxx.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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 +#include + +// 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 +// , 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()) +# 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 +# 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_dll.h b/third_party/cryptoppwin/include/cryptopp/config_dll.h new file mode 100644 index 00000000..73d16d9d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_dll.h 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 config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_dll.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script, +/// Visual Studio, +/// and FIPS DLL +/// 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, CRYPTOPP_DLL is defined to + /// __declspec(dllimport). + /// \details This macro has no effect on Unix & Linux. + /// \sa Visual Studio, + /// and FIPS DLL + /// 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, CRYPTOPP_DLL is defined to + /// __declspec(dllexport). + /// \details This macro has no effect on Unix & Linux. + /// \sa Visual Studio, + /// and FIPS DLL + /// 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 Visual Studio, + /// and FIPS DLL + /// 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 & Linux due to the source file dll.cpp. + /// \sa Visual Studio, + /// and FIPS DLL + /// 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 & Linux due to the source file dll.cpp. + /// \sa Visual Studio, + /// and FIPS DLL + /// 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 & Linux due to the source file dll.cpp. + /// \sa Visual Studio, + /// and FIPS DLL + /// 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 & Linux due to the source file dll.cpp. + /// \sa Visual Studio, + /// and FIPS DLL + /// 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 const qualifier. According to C++ rules + /// a declaration with const 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 __cedcl. On Unix & Linux + /// CRYPTOPP_API is defined to nothing. + /// \sa Visual Studio + /// 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_int.h b/third_party/cryptoppwin/include/cryptopp/config_int.h new file mode 100644 index 00000000..2eeda0e9 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_int.h 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 config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_int.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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 byte is in the Crypto++ +/// namespace. +/// \details The Crypto++ byte was originally in global namespace to avoid +/// ambiguity with other byte typedefs. byte was moved to CryptoPP namespace +/// at Crypto++ 6.0 due to C++17, std::byte and potential compile problems. +/// \sa Issue 442, +/// std::byte 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++ byte was originally in global namespace to avoid +/// ambiguity with other byte typedefs. byte was moved to CryptoPP namespace +/// at Crypto++ 6.0 due to C++17, std::byte and potential compile problems. +/// \sa CRYPTOPP_NO_GLOBAL_BYTE, Issue 442, +/// std::byte 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 word64 varies depending on the platform. + /// On Microsoft platforms it is unsigned __int64. On Unix & Linux + /// with LP64 data model it is unsigned long. On Unix & Linux with ILP32 + /// data model it is unsigned long long. + /// \since Crypto++ 1.0 + typedef unsigned long long word64; + + /// \brief 64-bit signed datatype + /// \details The typedef for sword64 varies depending on the platform. + /// On Microsoft platforms it is signed __int64. On Unix & Linux + /// with LP64 data model it is signed long. On Unix & Linux with ILP32 + /// data model it is signed long long. + /// \since Crypto++ 8.0 + typedef signed long long sword64; + + /// \brief 128-bit unsigned datatype + /// \details The typedef for word128 varies depending on the platform. + /// word128 is only available on 64-bit machines when + /// CRYPTOPP_WORD128_AVAILABLE is defined. + /// On Unix & Linux with LP64 data model it is __uint128_t. + /// 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. + ///
+	///    word64 x = W64LIT(0xffffffffffffffff);
+	///  
+ /// \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. + ///
+	///    sword64 x = SW64LIT(0xffffffffffffffff);
+	///  
+ /// \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 lword is an unsigned type, the value is +/// 0xffffffffffffffff. 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 hword varies depending on the platform. + /// On 32-bit platforms it is usually word16. On 64-bit platforms + /// it is usually word32. + /// \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 word varies depending on the platform. + /// On 32-bit platforms it is usually word32. On 64-bit platforms + /// it is usually word64. + /// \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 dword varies depending on the platform. + /// On 32-bit platforms it is usually word64. On 64-bit Unix & + /// Linux platforms it is usually word128. word128 is + /// not available on Microsoft platforms. word128 is only available + /// when CRYPTOPP_WORD128_AVAILABLE 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 __SIZEOF_INT128__ >= 16. + /// \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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_misc.h b/third_party/cryptoppwin/include/cryptopp/config_misc.h new file mode 100644 index 00000000..68e196cb --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_misc.h provides miscellaneous defines. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_misc.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_ns.h b/third_party/cryptoppwin/include/cryptopp/config_ns.h new file mode 100644 index 00000000..256b7916 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_ns.h provides defines for C++ and library +/// namespaces. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_ns.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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. +///
    +///
  • Name - namespace for names used with NameValuePairs and documented +/// in argnames.h +///
  • NaCl - namespace for NaCl test functions like crypto_box, +/// crypto_box_open, crypto_sign, and crypto_sign_open +///
  • Donna - namespace for curve25519 library operations. The name was +/// selected due to use of Langley and Moon's curve25519-donna. +///
  • Test - namespace for testing and benchmarks classes +///
  • Weak - namespace for weak and wounded algorithms, like ARC4, MD5 +/// and Pananma +///
+/// \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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_os.h b/third_party/cryptoppwin/include/cryptopp/config_os.h new file mode 100644 index 00000000..1a636c34 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 config_os.h provides defines for platforms and operating +/// systems. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_os.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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 diff --git a/third_party/cryptoppwin/include/cryptopp/config_ver.h b/third_party/cryptoppwin/include/cryptopp/config_ver.h new file mode 100644 index 00000000..c7e457c2 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/config_ver.h @@ -0,0 +1,98 @@ +// 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 config_ver.h provides defines for library and compiler +/// versions. +/// \details config.h 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 config.h while allowing Autoconf +/// to write new config_asm.h and new config_cxx.h using +/// its feature tests. +/// \note You should include config.h rather than config_ver.h +/// directly. +/// \sa Issue 835, +/// Make config.h more autoconf friendly, +/// Configure.sh script +/// 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__) && defined(_MSC_VER) +# define CRYPTOPP_MSVC_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 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 diff --git a/third_party/cryptoppwin/include/cryptopp/cpu.h b/third_party/cryptoppwin/include/cryptopp/cpu.h new file mode 100644 index 00000000..29ab6d42 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/cpu.h @@ -0,0 +1,1089 @@ +// cpu.h - originally written and placed in the public domain by Wei Dai +// updated for ARM and PowerPC by Jeffrey Walton. +// updated to split CPU_Query() and CPU_Probe() by Jeffrey Walton. + +/// \file cpu.h +/// \brief Functions for CPU features and intrinsics +/// \details The CPU functions are used in IA-32, ARM and PowerPC code paths. The +/// functions provide cpu specific feature testing on IA-32, ARM and PowerPC machines. +/// \details Feature detection uses CPUID on IA-32, like Intel and AMD. On other platforms +/// a two-part strategy is used. First, the library attempts to *Query* the OS for a feature, +/// like using Linux getauxval() or android_getCpuFeatures(). If that fails, then *Probe* +/// the cpu executing an instruction and an observe a SIGILL if unsupported. The general +/// pattern used by the library is: +///
+///    g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
+///    g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
+///    g_hasAES  = CPU_QueryAES() || CPU_ProbeAES();
+/// 
+/// \details Generally speaking, CPU_Query() is in the source file cpu.cpp because it +/// does not require special architectural flags. CPU_Probe() is in a source file that receives +/// architectural flags, like sse_simd.cpp, neon_simd.cpp and +/// ppc_simd.cpp. For example, compiling neon_simd.cpp on an ARM64 machine will +/// have -march=armv8-a applied during a compile to make the instruction set architecture +/// (ISA) available. +/// \details The cpu probes are expensive when compared to a standard OS feature query. The library +/// also avoids probes on Apple platforms because Apple's signal handling for SIGILLs appears to +/// corrupt memory. CPU_Probe() will unconditionally return false for Apple platforms. OpenSSL +/// experienced the same problem and moved away from SIGILL probes on Apple. + +#ifndef CRYPTOPP_CPU_H +#define CRYPTOPP_CPU_H + +#include "config.h" + +// Issue 340 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +// Applies to both X86/X32/X64 and ARM32/ARM64 +#if defined(CRYPTOPP_LLVM_CLANG_VERSION) || defined(CRYPTOPP_APPLE_CLANG_VERSION) + #define NEW_LINE "\n" + #define INTEL_PREFIX ".intel_syntax;" + #define INTEL_NOPREFIX ".intel_syntax;" + #define ATT_PREFIX ".att_syntax;" + #define ATT_NOPREFIX ".att_syntax;" +#elif defined(CRYPTOPP_GCC_VERSION) + #define NEW_LINE + #define INTEL_PREFIX ".intel_syntax prefix;" + #define INTEL_NOPREFIX ".intel_syntax noprefix;" + #define ATT_PREFIX ".att_syntax prefix;" + #define ATT_NOPREFIX ".att_syntax noprefix;" +#else + #define NEW_LINE + #define INTEL_PREFIX + #define INTEL_NOPREFIX + #define ATT_PREFIX + #define ATT_NOPREFIX +#endif + +// Thanks to v1ne at https://github.com/weidai11/cryptopp/pull/1133 +#define PERCENT_PASTE(x) "%" #x +#define PERCENT_REG(x) PERCENT_PASTE(x) + +#ifdef CRYPTOPP_GENERATE_X64_MASM + +#define CRYPTOPP_X86_ASM_AVAILABLE +#define CRYPTOPP_BOOL_X64 1 +#define CRYPTOPP_SSE2_ASM_AVAILABLE 1 +#define NAMESPACE_END + +#else + +NAMESPACE_BEGIN(CryptoPP) + +// ***************************** IA-32 ***************************** // + +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 || CRYPTOPP_DOXYGEN_PROCESSING + +#define CRYPTOPP_CPUID_AVAILABLE 1 + +// Hide from Doxygen +#ifndef CRYPTOPP_DOXYGEN_PROCESSING +// These should not be used directly +extern CRYPTOPP_DLL bool g_x86DetectionDone; +extern CRYPTOPP_DLL bool g_hasSSE2; +extern CRYPTOPP_DLL bool g_hasSSSE3; +extern CRYPTOPP_DLL bool g_hasSSE41; +extern CRYPTOPP_DLL bool g_hasSSE42; +extern CRYPTOPP_DLL bool g_hasMOVBE; +extern CRYPTOPP_DLL bool g_hasAESNI; +extern CRYPTOPP_DLL bool g_hasCLMUL; +extern CRYPTOPP_DLL bool g_hasAVX; +extern CRYPTOPP_DLL bool g_hasAVX2; +extern CRYPTOPP_DLL bool g_hasSHA; +extern CRYPTOPP_DLL bool g_hasADX; +extern CRYPTOPP_DLL bool g_isP4; +extern CRYPTOPP_DLL bool g_hasRDRAND; +extern CRYPTOPP_DLL bool g_hasRDSEED; +extern CRYPTOPP_DLL bool g_hasPadlockRNG; +extern CRYPTOPP_DLL bool g_hasPadlockACE; +extern CRYPTOPP_DLL bool g_hasPadlockACE2; +extern CRYPTOPP_DLL bool g_hasPadlockPHE; +extern CRYPTOPP_DLL bool g_hasPadlockPMM; +extern CRYPTOPP_DLL word32 g_cacheLineSize; + +CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features(); +CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 func, word32 subfunc, word32 output[4]); +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +/// \name IA-32 CPU FEATURES +//@{ + +/// \brief Determine SSE2 availability +/// \return true if SSE2 is determined to be available, false otherwise +/// \details MMX, SSE and SSE2 are core processor features for x86_64, and +/// the function return value is based on OSXSAVE. On i386 both +/// SSE2 and OSXSAVE are used for the return value. +/// \note This function is only available on Intel IA-32 platforms +inline bool HasSSE2() +{ +#if (CRYPTOPP_SSE2_ASM_AVAILABLE || CRYPTOPP_SSE2_INTRIN_AVAILABLE) + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSSE2; +#else + return false; +#endif +} + +/// \brief Determine SSSE3 availability +/// \return true if SSSE3 is determined to be available, false otherwise +/// \details HasSSSE3() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasSSSE3() +{ +#if CRYPTOPP_SSSE3_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSSSE3; +#else + return false; +#endif +} + +/// \brief Determine SSE4.1 availability +/// \return true if SSE4.1 is determined to be available, false otherwise +/// \details HasSSE41() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasSSE41() +{ +#if CRYPTOPP_SSE41_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSSE41; +#else + return false; +#endif +} + +/// \brief Determine SSE4.2 availability +/// \return true if SSE4.2 is determined to be available, false otherwise +/// \details HasSSE42() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasSSE42() +{ +#if CRYPTOPP_SSE42_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSSE42; +#else + return false; +#endif +} + +/// \brief Determine MOVBE availability +/// \return true if MOVBE is determined to be available, false otherwise +/// \details HasMOVBE() is a runtime check performed using CPUID +/// \since Crypto++ 8.3 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasMOVBE() +{ +#if CRYPTOPP_SSE42_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasMOVBE; +#else + return false; +#endif +} + +/// \brief Determine AES-NI availability +/// \return true if AES-NI is determined to be available, false otherwise +/// \details HasAESNI() is a runtime check performed using CPUID +/// \since Crypto++ 5.6.1 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasAESNI() +{ +#if CRYPTOPP_AESNI_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasAESNI; +#else + return false; +#endif +} + +/// \brief Determine Carryless Multiply availability +/// \return true if pclmulqdq is determined to be available, false otherwise +/// \details HasCLMUL() is a runtime check performed using CPUID +/// \since Crypto++ 5.6.1 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasCLMUL() +{ +#if CRYPTOPP_CLMUL_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasCLMUL; +#else + return false; +#endif +} + +/// \brief Determine SHA availability +/// \return true if SHA is determined to be available, false otherwise +/// \details HasSHA() is a runtime check performed using CPUID +/// \since Crypto++ 6.0 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasSHA() +{ +#if CRYPTOPP_SHANI_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSHA; +#else + return false; +#endif +} + +/// \brief Determine ADX availability +/// \return true if ADX is determined to be available, false otherwise +/// \details HasADX() is a runtime check performed using CPUID +/// \since Crypto++ 7.0 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasADX() +{ +#if CRYPTOPP_ADX_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasADX; +#else + return false; +#endif +} + +/// \brief Determine AVX availability +/// \return true if AVX is determined to be available, false otherwise +/// \details HasAVX() is a runtime check performed using CPUID +/// \since Crypto++ 8.0 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasAVX() +{ +#if CRYPTOPP_AVX_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasAVX; +#else + return false; +#endif +} + +/// \brief Determine AVX2 availability +/// \return true if AVX2 is determined to be available, false otherwise +/// \details HasAVX2() is a runtime check performed using CPUID +/// \since Crypto++ 8.0 +/// \note This function is only available on Intel IA-32 platforms +inline bool HasAVX2() +{ +#if CRYPTOPP_AVX2_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasAVX2; +#else + return false; +#endif +} + +/// \brief Determine RDRAND availability +/// \return true if RDRAND is determined to be available, false otherwise +/// \details HasRDRAND() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasRDRAND() +{ +#if CRYPTOPP_RDRAND_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasRDRAND; +#else + return false; +#endif +} + +/// \brief Determine RDSEED availability +/// \return true if RDSEED is determined to be available, false otherwise +/// \details HasRDSEED() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasRDSEED() +{ +#if CRYPTOPP_RDSEED_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasRDSEED; +#else + return false; +#endif +} + +/// \brief Determine Padlock RNG availability +/// \return true if VIA Padlock RNG is determined to be available, false otherwise +/// \details HasPadlockRNG() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasPadlockRNG() +{ +#if CRYPTOPP_PADLOCK_RNG_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasPadlockRNG; +#else + return false; +#endif +} + +/// \brief Determine Padlock ACE availability +/// \return true if VIA Padlock ACE is determined to be available, false otherwise +/// \details HasPadlockACE() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasPadlockACE() +{ +#if CRYPTOPP_PADLOCK_ACE_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasPadlockACE; +#else + return false; +#endif +} + +/// \brief Determine Padlock ACE2 availability +/// \return true if VIA Padlock ACE2 is determined to be available, false otherwise +/// \details HasPadlockACE2() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasPadlockACE2() +{ +#if CRYPTOPP_PADLOCK_ACE2_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasPadlockACE2; +#else + return false; +#endif +} + +/// \brief Determine Padlock PHE availability +/// \return true if VIA Padlock PHE is determined to be available, false otherwise +/// \details HasPadlockPHE() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasPadlockPHE() +{ +#if CRYPTOPP_PADLOCK_PHE_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasPadlockPHE; +#else + return false; +#endif +} + +/// \brief Determine Padlock PMM availability +/// \return true if VIA Padlock PMM is determined to be available, false otherwise +/// \details HasPadlockPMM() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool HasPadlockPMM() +{ +#if CRYPTOPP_PADLOCK_PMM_AVAILABLE + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasPadlockPMM; +#else + return false; +#endif +} + +/// \brief Determine if the CPU is an Intel P4 +/// \return true if the CPU is a P4, false otherwise +/// \details IsP4() is a runtime check performed using CPUID +/// \note This function is only available on Intel IA-32 platforms +inline bool IsP4() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_isP4; +} + +/// \brief Provides the cache line size +/// \return lower bound on the size of a cache line in bytes, if available +/// \details GetCacheLineSize() returns the lower bound on the size of a cache line, if it +/// is available. If the value is not available at runtime, then 32 is returned for a 32-bit +/// processor and 64 is returned for a 64-bit processor. +/// \details x86/x32/x64 uses CPUID to determine the value and it is usually accurate. PowerPC +/// and AIX also makes the value available to user space and it is also usually accurate. The +/// ARM processor equivalent is a privileged instruction, so a compile time value is returned. +inline int GetCacheLineSize() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_cacheLineSize; +} +//@} + +#endif // CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 + +// ***************************** ARM-32, Aarch32 and Aarch64 ***************************** // + +#if CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8 || CRYPTOPP_DOXYGEN_PROCESSING + +// Hide from Doxygen +#ifndef CRYPTOPP_DOXYGEN_PROCESSING +extern bool g_ArmDetectionDone; +extern bool g_hasARMv7; +extern bool g_hasNEON; +extern bool g_hasPMULL; +extern bool g_hasCRC32; +extern bool g_hasAES; +extern bool g_hasSHA1; +extern bool g_hasSHA2; +extern bool g_hasSHA512; +extern bool g_hasSHA3; +extern bool g_hasSM3; +extern bool g_hasSM4; +void CRYPTOPP_API DetectArmFeatures(); +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +/// \name ARM A-32, Aarch32 and AArch64 CPU FEATURES +//@{ + +/// \brief Determine if an ARM processor is ARMv7 or above +/// \return true if the hardware is ARMv7 or above, false otherwise. +/// \details Some AES code requires ARMv7 or above +/// \since Crypto++ 8.0 +/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms +inline bool HasARMv7() +{ + // ASIMD is a core feature on Aarch32 and Aarch64 like SSE2 is a core feature on x86_64 +#if defined(__aarch32__) || defined(__aarch64__) + return true; +#else + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasARMv7; +#endif +} + +/// \brief Determine if an ARM processor has Advanced SIMD available +/// \return true if the hardware is capable of Advanced SIMD at runtime, false otherwise. +/// \details Advanced SIMD instructions are available under most ARMv7, Aarch32 and Aarch64. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mfpu=neon (32-bit) or -march=armv8-a +/// (64-bit). Also see ARM's __ARM_NEON preprocessor macro. +/// \since Crypto++ 5.6.4 +/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms +inline bool HasNEON() +{ + // ASIMD is a core feature on Aarch32 and Aarch64 like SSE2 is a core feature on x86_64 +#if defined(CRYPTOPP_ARM_ASIMD_AVAILABLE) + return true; +#elif defined(CRYPTOPP_ARM_NEON_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasNEON; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has CRC32 available +/// \return true if the hardware is capable of CRC32 at runtime, false otherwise. +/// \details CRC32 instructions provide access to the processor's CRC-32 and CRC-32C +/// instructions. They are provided by ARM C Language Extensions 2.0 (ACLE 2.0) and +/// available under Aarch32 and Aarch64. +/// \details Runtime support requires compile time support. When compiling with GCC, +/// you may need to compile with -march=armv8-a+crc; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRC32 preprocessor macro. +/// \since Crypto++ 5.6.4 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasCRC32() +{ +#if defined(CRYPTOPP_ARM_CRC32_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasCRC32; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has AES available +/// \return true if the hardware is capable of AES at runtime, false otherwise. +/// \details AES is part of the optional Crypto extensions on Aarch32 and Aarch64. They are +/// accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -march=armv8-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 5.6.4 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasAES() +{ +#if defined(CRYPTOPP_ARM_AES_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasAES; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor provides Polynomial Multiplication +/// \return true if the hardware is capable of polynomial multiplications at runtime, +/// false otherwise. +/// \details The multiplication instructions are available under Aarch32 and Aarch64. +/// \details Runtime support requires compile time support. When compiling with GCC, +/// you may need to compile with -march=armv8-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 5.6.4 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasPMULL() +{ +#if defined(CRYPTOPP_ARM_PMULL_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasPMULL; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has SHA1 available +/// \return true if the hardware is capable of SHA1 at runtime, false otherwise. +/// \details SHA1 is part of the optional Crypto extensions on Aarch32 and Aarch64. They are +/// accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -march=armv8-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 5.6.4 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasSHA1() +{ +#if defined(CRYPTOPP_ARM_SHA1_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasSHA1; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has SHA256 available +/// \return true if the hardware is capable of SHA256 at runtime, false otherwise. +/// \details SHA256 is part of the optional Crypto extensions on Aarch32 and Aarch64. They are +/// accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -march=armv8-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 5.6.4 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasSHA2() +{ +#if defined(CRYPTOPP_ARM_SHA2_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasSHA2; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has SHA3 available +/// \return true if the hardware is capable of SHA3 at runtime, false otherwise. +/// \details SHA3 is part of the ARMv8.2 Crypto extensions on Aarch32 and Aarch64. They +/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you +/// may need to compile with -march=armv8.2-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 8.0 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasSHA3() +{ +#if defined(CRYPTOPP_ARM_SHA3_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasSHA3; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has SHA512 available +/// \return true if the hardware is capable of SHA512 at runtime, false otherwise. +/// \details SHA512 is part of the ARMv8.2 Crypto extensions on Aarch32 and Aarch64. They +/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you +/// may need to compile with -march=armv8.2-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 8.0 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasSHA512() +{ +#if defined(CRYPTOPP_ARM_SHA512_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasSHA512; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has SM3 available +/// \return true if the hardware is capable of SM3 at runtime, false otherwise. +/// \details SM3 is part of the ARMv8.2 Crypto extensions on Aarch32 and Aarch64. They +/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you +/// may need to compile with -march=armv8.2-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 8.0 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasSM3() +{ +#if defined(CRYPTOPP_ARM_SM3_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasSM3; +#else + return false; +#endif +} + +/// \brief Determine if an ARM processor has SM4 available +/// \return true if the hardware is capable of SM4 at runtime, false otherwise. +/// \details SM4 is part of the ARMv8.2 Crypto extensions on Aarch32 and Aarch64. They +/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0). +/// \details Runtime support requires compile time support. When compiling with GCC, you +/// may need to compile with -march=armv8.2-a+crypto; while Apple requires +/// -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro. +/// \since Crypto++ 8.0 +/// \note This function is only available on Aarch32 and Aarch64 platforms +inline bool HasSM4() +{ +#if defined(CRYPTOPP_ARM_SM4_AVAILABLE) + if (!g_ArmDetectionDone) + DetectArmFeatures(); + return g_hasSM4; +#else + return false; +#endif +} + +//@} + +#endif // CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8 + +// ***************************** PowerPC ***************************** // + +#if CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 || CRYPTOPP_DOXYGEN_PROCESSING + +// Hide from Doxygen +#ifndef CRYPTOPP_DOXYGEN_PROCESSING +extern bool g_PowerPcDetectionDone; +extern bool g_hasAltivec; +extern bool g_hasPower7; +extern bool g_hasPower8; +extern bool g_hasPower9; +extern bool g_hasAES; +extern bool g_hasPMULL; +extern bool g_hasSHA256; +extern bool g_hasSHA512; +extern bool g_hasDARN; +extern word32 g_cacheLineSize; +void CRYPTOPP_API DetectPowerPcFeatures(); +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +/// \name POWERPC CPU FEATURES +//@{ + +/// \brief Determine if a PowerPC processor has Altivec available +/// \return true if the hardware is capable of Altivec at runtime, false otherwise. +/// \details Altivec instructions are available on modern PowerPCs. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power4; while IBM XL C/C++ compilers require +/// -qarch=pwr6 -qaltivec. Also see PowerPC's _ALTIVEC_ preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasAltivec() +{ +#if CRYPTOPP_ALTIVEC_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasAltivec; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has Power7 available +/// \return true if the hardware is capable of Power7 at runtime, false otherwise. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power7; while IBM XL C/C++ compilers require +/// -qarch=pwr7 -qaltivec. Also see PowerPC's _ALTIVEC_ preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasPower7() +{ +#if CRYPTOPP_POWER7_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasPower7; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has Power8 available +/// \return true if the hardware is capable of Power8 at runtime, false otherwise. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power8; while IBM XL C/C++ compilers require +/// -qarch=pwr8 -qaltivec. Also see PowerPC's _ALTIVEC_ preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasPower8() +{ +#if CRYPTOPP_POWER8_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasPower8; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has Power9 available +/// \return true if the hardware is capable of Power9 at runtime, false otherwise. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power9; while IBM XL C/C++ compilers require +/// -qarch=pwr9 -qaltivec. Also see PowerPC's _ALTIVEC_ preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasPower9() +{ +#if CRYPTOPP_POWER9_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasPower9; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has AES available +/// \return true if the hardware is capable of AES at runtime, false otherwise. +/// \details AES is part of the in-crypto extensions on Power8 and Power9. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power8; while IBM XL C/C++ compilers require +/// -qarch=pwr8 -qaltivec. Also see PowerPC's __CRYPTO preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasAES() +{ +#if CRYPTOPP_POWER8_AES_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasAES; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has Polynomial Multiply available +/// \return true if the hardware is capable of PMULL at runtime, false otherwise. +/// \details PMULL is part of the in-crypto extensions on Power8 and Power9. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power8; while IBM XL C/C++ compilers require +/// -qarch=pwr8 -qaltivec. Also see PowerPC's __CRYPTO preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasPMULL() +{ +#if CRYPTOPP_POWER8_VMULL_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasPMULL; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has SHA256 available +/// \return true if the hardware is capable of SHA256 at runtime, false otherwise. +/// \details SHA is part of the in-crypto extensions on Power8 and Power9. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power8; while IBM XL C/C++ compilers require +/// -qarch=pwr8 -qaltivec. Also see PowerPC's __CRYPTO preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasSHA256() +{ +#if CRYPTOPP_POWER8_SHA_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasSHA256; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has SHA512 available +/// \return true if the hardware is capable of SHA512 at runtime, false otherwise. +/// \details SHA is part of the in-crypto extensions on Power8 and Power9. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power8; while IBM XL C/C++ compilers require +/// -qarch=pwr8 -qaltivec. Also see PowerPC's __CRYPTO preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasSHA512() +{ +#if CRYPTOPP_POWER8_SHA_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_hasSHA512; +#else + return false; +#endif +} + +/// \brief Determine if a PowerPC processor has DARN available +/// \return true if the hardware is capable of DARN at runtime, false otherwise. +/// \details Runtime support requires compile time support. When compiling with GCC, you may +/// need to compile with -mcpu=power9; while IBM XL C/C++ compilers require +/// -qarch=pwr9 -qaltivec. Also see PowerPC's _ALTIVEC_ preprocessor macro. +/// \note This function is only available on PowerPC and PowerPC-64 platforms +inline bool HasDARN() +{ +#if CRYPTOPP_POWER9_AVAILABLE + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + // see comments in cpu.cpp +# if defined(__ibmxl__) && defined(__linux__) + return false; +# else + return g_hasDARN; +# endif +#else + return false; +#endif +} + +/// \brief Provides the cache line size +/// \return lower bound on the size of a cache line in bytes, if available +/// \details GetCacheLineSize() returns the lower bound on the size of a cache line, if it +/// is available. If the value is not available at runtime, then 32 is returned for a 32-bit +/// processor and 64 is returned for a 64-bit processor. +/// \details x86/x32/x64 uses CPUID to determine the value and it is usually accurate. PowerPC +/// and AIX also makes the value available to user space and it is also usually accurate. The +/// ARM processor equivalent is a privileged instruction, so a compile time value is returned. +inline int GetCacheLineSize() +{ + if (!g_PowerPcDetectionDone) + DetectPowerPcFeatures(); + return g_cacheLineSize; +} + +//@} + +#endif // CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 + +// ***************************** L1 cache line ***************************** // + +// Non-Intel systems +#if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) +/// \brief Provides the cache line size +/// \return lower bound on the size of a cache line in bytes, if available +/// \details GetCacheLineSize() returns the lower bound on the size of a cache line, if it +/// is available. If the value is not available at runtime, then 32 is returned for a 32-bit +/// processor and 64 is returned for a 64-bit processor. +/// \details x86/x32/x64 uses CPUID to determine the value and it is usually accurate. PowerPC +/// and AIX also makes the value available to user space and it is also usually accurate. The +/// ARM processor equivalent is a privileged instruction, so a compile time value is returned. +inline int GetCacheLineSize() +{ + return CRYPTOPP_L1_CACHE_LINE_SIZE; +} +#endif // Non-Intel systems + +#endif // CRYPTOPP_GENERATE_X64_MASM + +// ***************************** Inline ASM Helper ***************************** // + +#ifndef CRYPTOPP_DOXYGEN_PROCESSING + +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 + +#ifdef CRYPTOPP_GENERATE_X64_MASM + #define AS1(x) x*newline* + #define AS2(x, y) x, y*newline* + #define AS3(x, y, z) x, y, z*newline* + #define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline* + #define ASL(x) label##x:*newline* + #define ASJ(x, y, z) x label##y*newline* + #define ASC(x, y) x label##y*newline* + #define AS_HEX(y) 0##y##h +#elif defined(CRYPTOPP_MSC_VERSION) || defined(__BORLANDC__) + #define AS1(x) __asm {x} + #define AS2(x, y) __asm {x, y} + #define AS3(x, y, z) __asm {x, y, z} + #define ASS(x, y, a, b, c, d) __asm {x, y, (a)*64+(b)*16+(c)*4+(d)} + #define ASL(x) __asm {label##x:} + #define ASJ(x, y, z) __asm {x label##y} + #define ASC(x, y) __asm {x label##y} + #define CRYPTOPP_NAKED __declspec(naked) + #define AS_HEX(y) 0x##y +#else + // define these in two steps to allow arguments to be expanded + #define GNU_AS1(x) #x ";" NEW_LINE + #define GNU_AS2(x, y) #x ", " #y ";" NEW_LINE + #define GNU_AS3(x, y, z) #x ", " #y ", " #z ";" NEW_LINE + #define GNU_ASL(x) "\n" #x ":" NEW_LINE +// clang 5.0.0 and apple clang 9.0.0 don't support numerical backward jumps +#if (CRYPTOPP_LLVM_CLANG_VERSION >= 50000) || (CRYPTOPP_APPLE_CLANG_VERSION >= 90000) + #define GNU_ASJ(x, y, z) ATT_PREFIX ";" NEW_LINE #x " " #y #z ";" NEW_LINE INTEL_PREFIX ";" NEW_LINE +#else + #define GNU_ASJ(x, y, z) #x " " #y #z ";" NEW_LINE +#endif + #define AS1(x) GNU_AS1(x) + #define AS2(x, y) GNU_AS2(x, y) + #define AS3(x, y, z) GNU_AS3(x, y, z) + #define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";" + #define ASL(x) GNU_ASL(x) + #define ASJ(x, y, z) GNU_ASJ(x, y, z) + #define ASC(x, y) #x " " #y ";" + #define CRYPTOPP_NAKED + #define AS_HEX(y) 0x##y +#endif + +#define IF0(y) +#define IF1(y) y + +#ifdef CRYPTOPP_GENERATE_X64_MASM +#define ASM_MOD(x, y) ((x) MOD (y)) +#define XMMWORD_PTR XMMWORD PTR +#else +// GNU assembler doesn't seem to have mod operator +#define ASM_MOD(x, y) ((x)-((x)/(y))*(y)) +// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM +#define XMMWORD_PTR +#endif + +#if CRYPTOPP_BOOL_X86 + #define AS_REG_1 ecx + #define AS_REG_2 edx + #define AS_REG_3 esi + #define AS_REG_4 edi + #define AS_REG_5 eax + #define AS_REG_6 ebx + #define AS_REG_7 ebp + #define AS_REG_1d ecx + #define AS_REG_2d edx + #define AS_REG_3d esi + #define AS_REG_4d edi + #define AS_REG_5d eax + #define AS_REG_6d ebx + #define AS_REG_7d ebp + #define WORD_SZ 4 + #define WORD_REG(x) e##x + #define WORD_PTR DWORD PTR + #define AS_PUSH_IF86(x) AS1(push e##x) + #define AS_POP_IF86(x) AS1(pop e##x) + #define AS_JCXZ jecxz +#elif CRYPTOPP_BOOL_X32 + #define AS_REG_1 ecx + #define AS_REG_2 edx + #define AS_REG_3 r8d + #define AS_REG_4 r9d + #define AS_REG_5 eax + #define AS_REG_6 r10d + #define AS_REG_7 r11d + #define AS_REG_1d ecx + #define AS_REG_2d edx + #define AS_REG_3d r8d + #define AS_REG_4d r9d + #define AS_REG_5d eax + #define AS_REG_6d r10d + #define AS_REG_7d r11d + #define WORD_SZ 4 + #define WORD_REG(x) e##x + #define WORD_PTR DWORD PTR + #define AS_PUSH_IF86(x) AS1(push r##x) + #define AS_POP_IF86(x) AS1(pop r##x) + #define AS_JCXZ jecxz +#elif CRYPTOPP_BOOL_X64 + #ifdef CRYPTOPP_GENERATE_X64_MASM + #define AS_REG_1 rcx + #define AS_REG_2 rdx + #define AS_REG_3 r8 + #define AS_REG_4 r9 + #define AS_REG_5 rax + #define AS_REG_6 r10 + #define AS_REG_7 r11 + #define AS_REG_1d ecx + #define AS_REG_2d edx + #define AS_REG_3d r8d + #define AS_REG_4d r9d + #define AS_REG_5d eax + #define AS_REG_6d r10d + #define AS_REG_7d r11d + #else + #define AS_REG_1 rdi + #define AS_REG_2 rsi + #define AS_REG_3 rdx + #define AS_REG_4 rcx + #define AS_REG_5 r8 + #define AS_REG_6 r9 + #define AS_REG_7 r10 + #define AS_REG_1d edi + #define AS_REG_2d esi + #define AS_REG_3d edx + #define AS_REG_4d ecx + #define AS_REG_5d r8d + #define AS_REG_6d r9d + #define AS_REG_7d r10d + #endif + #define WORD_SZ 8 + #define WORD_REG(x) r##x + #define WORD_PTR QWORD PTR + #define AS_PUSH_IF86(x) + #define AS_POP_IF86(x) + #define AS_JCXZ jrcxz +#endif + +// helper macro for stream cipher output +#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\ + AS2( test inputPtr, inputPtr)\ + ASC( jz, labelPrefix##3)\ + AS2( test inputPtr, 15)\ + ASC( jnz, labelPrefix##7)\ + AS2( pxor xmm##x0, [inputPtr+p0*16])\ + AS2( pxor xmm##x1, [inputPtr+p1*16])\ + AS2( pxor xmm##x2, [inputPtr+p2*16])\ + AS2( pxor xmm##x3, [inputPtr+p3*16])\ + AS2( add inputPtr, increment*16)\ + ASC( jmp, labelPrefix##3)\ + ASL(labelPrefix##7)\ + AS2( movdqu xmm##t, [inputPtr+p0*16])\ + AS2( pxor xmm##x0, xmm##t)\ + AS2( movdqu xmm##t, [inputPtr+p1*16])\ + AS2( pxor xmm##x1, xmm##t)\ + AS2( movdqu xmm##t, [inputPtr+p2*16])\ + AS2( pxor xmm##x2, xmm##t)\ + AS2( movdqu xmm##t, [inputPtr+p3*16])\ + AS2( pxor xmm##x3, xmm##t)\ + AS2( add inputPtr, increment*16)\ + ASL(labelPrefix##3)\ + AS2( test outputPtr, 15)\ + ASC( jnz, labelPrefix##8)\ + AS2( movdqa [outputPtr+p0*16], xmm##x0)\ + AS2( movdqa [outputPtr+p1*16], xmm##x1)\ + AS2( movdqa [outputPtr+p2*16], xmm##x2)\ + AS2( movdqa [outputPtr+p3*16], xmm##x3)\ + ASC( jmp, labelPrefix##9)\ + ASL(labelPrefix##8)\ + AS2( movdqu [outputPtr+p0*16], xmm##x0)\ + AS2( movdqu [outputPtr+p1*16], xmm##x1)\ + AS2( movdqu [outputPtr+p2*16], xmm##x2)\ + AS2( movdqu [outputPtr+p3*16], xmm##x3)\ + ASL(labelPrefix##9)\ + AS2( add outputPtr, increment*16) + +#endif // CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 + +#endif // Not CRYPTOPP_DOXYGEN_PROCESSING + +NAMESPACE_END + +// Issue 340 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif + +#endif // CRYPTOPP_CPU_H diff --git a/third_party/cryptoppwin/include/cryptopp/crc.h b/third_party/cryptoppwin/include/cryptopp/crc.h new file mode 100644 index 00000000..17e5977b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/crc.h @@ -0,0 +1,90 @@ +// crc.h - originally written and placed in the public domain by Wei Dai + +/// \file crc.h +/// \brief Classes for CRC-32 and CRC-32C checksum algorithm + +#ifndef CRYPTOPP_CRC32_H +#define CRYPTOPP_CRC32_H + +#include "cryptlib.h" + +NAMESPACE_BEGIN(CryptoPP) + +const word32 CRC32_NEGL = 0xffffffffL; + +#if (CRYPTOPP_LITTLE_ENDIAN) +#define CRC32_INDEX(c) (c & 0xff) +#define CRC32_SHIFTED(c) (c >> 8) +#else +#define CRC32_INDEX(c) (c >> 24) +#define CRC32_SHIFTED(c) (c << 8) +#endif + +/// \brief CRC-32 Checksum Calculation +/// \details Uses CRC polynomial 0xEDB88320 +class CRC32 : public HashTransformation +{ +public: + 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();} + + /// \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);} + + /// \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(&m_crc)[i];} + + std::string AlgorithmProvider() const; + +protected: + void Reset() {m_crc = CRC32_NEGL;} + +private: + static const word32 m_tab[256]; + word32 m_crc; +}; + +/// \brief CRC-32C Checksum Calculation +/// \details Uses CRC polynomial 0x82F63B78 +/// \since Crypto++ 5.6.4 +class CRC32C : public HashTransformation +{ +public: + 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();} + + /// \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);} + + /// \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(&m_crc)[i];} + + std::string AlgorithmProvider() const; + +protected: + void Reset() {m_crc = CRC32_NEGL;} + +private: + static const word32 m_tab[256]; + word32 m_crc; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/cryptlib.h b/third_party/cryptoppwin/include/cryptopp/cryptlib.h new file mode 100644 index 00000000..4a5c83bf --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/cryptlib.h @@ -0,0 +1,3384 @@ +// cryptlib.h - originally written and placed in the public domain by Wei Dai + +/// \file cryptlib.h +/// \brief Abstract base classes that provide a uniform interface to this library. + +/*! \mainpage Crypto++ Library 8.9 API Reference +
+
Abstract Base Classes
+ cryptlib.h +
Authenticated Encryption Modes
+ CCM, EAX, \ref GCM "GCM (2K tables)", \ref GCM "GCM (64K tables)" +
Block Ciphers
+ \ref Rijndael "AES", ARIA, Weak::ARC4, Blowfish, BTEA, \ref CHAM128 "CHAM (64/128)", Camellia, + \ref CAST128 "CAST (128/256)", DES, \ref DES_EDE2 "2-key Triple-DES", \ref DES_EDE3 "3-key Triple-DES", + \ref DES_XEX3 "DESX", GOST, HIGHT, IDEA, LEA, \ref LR "Luby-Rackoff", \ref Kalyna128 "Kalyna (128/256/512)", + MARS, RC2, RC5, RC6, \ref SAFER_K "SAFER-K", \ref SAFER_SK "SAFER-SK", SEED, Serpent, + \ref SHACAL2 "SHACAL-2", SHARK, \ref SIMECK64 "SIMECK (32/64)" SKIPJACK, SM4, Square, TEA, + \ref ThreeWay "3-Way", \ref Threefish256 "Threefish (256/512/1024)", Twofish, XTEA +
Stream Ciphers
+ \ref ChaCha "ChaCha (8/12/20)", \ref HC128 "HC-128/256", \ref Panama "Panama-LE", \ref Panama "Panama-BE", + Rabbit, Salsa20, \ref SEAL "SEAL-LE", \ref SEAL "SEAL-BE", WAKE, XSalsa20 +
Hash Functions
+ BLAKE2s, BLAKE2b, \ref Keccak "Keccak (F1600)", SHA1, SHA224, SHA256, SHA384, SHA512, + \ref SHA3 "SHA-3", SM3, LSH (256/512), Tiger, RIPEMD160, RIPEMD256, SipHash, Whirlpool, + Weak::MD2, Weak::MD4, Weak::MD5 +
Non-Cryptographic Checksums
+ CRC32, CRC32C, Adler32 +
Message Authentication Codes
+ BLAKE2b, BLAKE2s, CBC_MAC, CMAC, DMAC, \ref GCM "GCM (GMAC)", HMAC, Poly1305, TTMAC, VMAC +
Random Number Generators
+ NullRNG, LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, + NIST Hash_DRBG and HMAC_DRBG, \ref MersenneTwister "MersenneTwister (MT19937 and MT19937-AR)", + DARN, RDRAND, RDSEED +
Key Derivation and Password-based Cryptography
+ HKDF, \ref PKCS12_PBKDF "PBKDF (PKCS #12)", \ref PKCS5_PBKDF1 "PBKDF-1 (PKCS #5)", + \ref PKCS5_PBKDF2_HMAC "PBKDF-2/HMAC (PKCS #5)" +
Public Key Cryptosystems
+ DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES +
Public Key Signature Schemes
+ DSA, DSA2, \ref ed25519 "Ed25519", GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, + RabinSS, RWSS, ESIGN +
Key Agreement
+ DH, DH2, \ref x25519 "X25519", \ref MQV_Domain "MQV", \ref HMQV_Domain "HMQV", + \ref FHMQV_Domain "FHMQV", ECDH, x25519, ECMQV, ECHMQV, ECFHMQV, XTR_DH +
Algebraic Structures
+ Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver, + ModularArithmetic, MontgomeryRepresentation, GFP2_ONB, GF2NP, GF256, GF2_32, EC2N, ECP +
Secret Sharing and Information Dispersal
+ SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery +
Compression
+ Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor +
Input Source Classes
+ StringSource, ArraySource, VectorSource, FileSource, RandomNumberSource +
Output Sink Classes
+ StringSinkTemplate, StringSink, VectorSink, ArraySink, FileSink, RandomNumberSink +
Filter Wrappers
+ StreamTransformationFilter, AuthenticatedEncryptionFilter, AuthenticatedDecryptionFilter, HashFilter, + HashVerificationFilter, SignerFilter, SignatureVerificationFilter +
Binary to Text Encoders and Decoders
+ HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base64URLEncoder, Base64URLDecoder, Base32Encoder, + Base32Decoder +
Wrappers for OS features
+ Timer, ThreadUserTimer + +
+ + + +

This reference manual is a work in progress. Some classes lack detailed descriptions. +

Click here to download a zip archive containing this manual. +

Thanks to Ryan Phillips for providing the Doxygen configuration file +and getting us started on the manual. +*/ + +#ifndef CRYPTOPP_CRYPTLIB_H +#define CRYPTOPP_CRYPTLIB_H + +#include "config.h" +#include "stdcpp.h" +#include "trap.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) +# pragma warning(disable: 4127 4189 4505 4702) +# if (CRYPTOPP_MSC_VERSION >= 1933) +# pragma warning(disable: 5264) +# endif +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// forward declarations +class Integer; +class RandomNumberGenerator; +class BufferedTransformation; + +/// \brief Specifies a direction for a cipher to operate +/// \sa BlockTransformation::IsForwardTransformation(), BlockTransformation::IsPermutation(), BlockTransformation::GetCipherDirection() +enum CipherDir { + /// \brief the cipher is performing encryption + ENCRYPTION, + /// \brief the cipher is performing decryption + DECRYPTION}; + +/// \brief Represents infinite time +CRYPTOPP_CONST_OR_CONSTEXPR unsigned long INFINITE_TIME = ULONG_MAX; + +// VC60 workaround: using enums as template parameters causes problems +/// \brief Converts an enumeration to a type suitable for use as a template parameter +template +struct EnumToType +{ + static ENUM_TYPE ToEnum() {return static_cast(VALUE);} +}; + +/// \brief Provides the byte ordering +/// \details Big-endian and little-endian modes are supported. Bi-endian and PDP-endian modes +/// are not supported. +enum ByteOrder { + /// \brief byte order is little-endian + LITTLE_ENDIAN_ORDER = 0, + /// \brief byte order is big-endian + BIG_ENDIAN_ORDER = 1}; + +/// \brief Provides a constant for LittleEndian +typedef EnumToType LittleEndian; +/// \brief Provides a constant for BigEndian +typedef EnumToType BigEndian; + +/// \brief Base class for all exceptions thrown by the library +/// \details All library exceptions directly or indirectly inherit from the Exception class. +/// The Exception class itself inherits from std::exception. The library does not use +/// std::runtime_error derived classes. +class CRYPTOPP_DLL Exception : public std::exception +{ +public: + /// \enum ErrorType + /// \brief Error types or categories + enum ErrorType { + /// \brief A method was called which was not implemented + NOT_IMPLEMENTED, + /// \brief An invalid argument was detected + INVALID_ARGUMENT, + /// \brief BufferedTransformation received a Flush(true) signal but can't flush buffers + CANNOT_FLUSH, + /// \brief Data integerity check, such as CRC or MAC, failed + DATA_INTEGRITY_CHECK_FAILED, + /// \brief Input data was received that did not conform to expected format + INVALID_DATA_FORMAT, + /// \brief Error reading from input device or writing to output device + IO_ERROR, + /// \brief Some other error occurred not belonging to other categories + OTHER_ERROR + }; + + virtual ~Exception() throw() {} + + /// \brief Construct a new Exception + explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {} + + /// \brief Retrieves a C-string describing the exception + const char *what() const throw() {return (m_what.c_str());} + /// \brief Retrieves a string describing the exception + const std::string &GetWhat() const {return m_what;} + /// \brief Sets the error string for the exception + void SetWhat(const std::string &s) {m_what = s;} + /// \brief Retrieves the error type for the exception + ErrorType GetErrorType() const {return m_errorType;} + /// \brief Sets the error type for the exceptions + void SetErrorType(ErrorType errorType) {m_errorType = errorType;} + +private: + ErrorType m_errorType; + std::string m_what; +}; + +/// \brief An invalid argument was detected +class CRYPTOPP_DLL InvalidArgument : public Exception +{ +public: + /// \brief Construct an InvalidArgument + /// \param s the message for the exception + /// \details The member function what() returns s. + explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {} +}; + +/// \brief Input data was received that did not conform to expected format +class CRYPTOPP_DLL InvalidDataFormat : public Exception +{ +public: + /// \brief Construct an InvalidDataFormat + /// \param s the message for the exception + /// \details The member function what() returns s. + explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {} +}; + +/// \brief A decryption filter encountered invalid ciphertext +class CRYPTOPP_DLL InvalidCiphertext : public InvalidDataFormat +{ +public: + /// \brief Construct an InvalidCiphertext + /// \param s the message for the exception + /// \details The member function what() returns s. + explicit InvalidCiphertext(const std::string &s) : InvalidDataFormat(s) {} +}; + +/// \brief A method was called which was not implemented +class CRYPTOPP_DLL NotImplemented : public Exception +{ +public: + /// \brief Construct an NotImplemented + /// \param s the message for the exception + /// \details The member function what() returns s. + explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {} +}; + +/// \brief Flush(true) was called but it can't completely flush its buffers +class CRYPTOPP_DLL CannotFlush : public Exception +{ +public: + /// \brief Construct an CannotFlush + /// \param s the message for the exception + /// \details The member function what() returns s. + explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {} +}; + +/// \brief The operating system reported an error +class CRYPTOPP_DLL OS_Error : public Exception +{ +public: + virtual ~OS_Error() throw() {} + + /// \brief Construct an OS_Error + /// \param errorType the error type + /// \param s the message for the exception + /// \param operation the operation for the exception + /// \param errorCode the error code + /// \details The member function what() returns s. + OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode) + : Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {} + + /// \brief Retrieve the operating system API that reported the error + const std::string & GetOperation() const {return m_operation;} + /// \brief Retrieve the error code returned by the operating system + int GetErrorCode() const {return m_errorCode;} + +protected: + std::string m_operation; + int m_errorCode; +}; + +/// \brief Returns a decoding results +struct CRYPTOPP_DLL DecodingResult +{ + /// \brief Constructs a DecodingResult + /// \details isValidCoding is initialized to false and messageLength is + /// initialized to 0. + explicit DecodingResult() : isValidCoding(false), messageLength(0) {} + /// \brief Constructs a DecodingResult + /// \param len the message length + /// \details isValidCoding is initialized to true. + explicit DecodingResult(size_t len) : isValidCoding(true), messageLength(len) {} + + /// \brief Compare two DecodingResult + /// \param rhs the other DecodingResult + /// \return true if either isValidCoding or messageLength is \a not equal, + /// false otherwise + bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;} + /// \brief Compare two DecodingResult + /// \param rhs the other DecodingResult + /// \return true if either isValidCoding or messageLength is \a not equal, + /// false otherwise + /// \details Returns !operator==(rhs). + bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);} + + /// \brief Flag to indicate the decoding is valid + bool isValidCoding; + /// \brief Recovered message length if isValidCoding is true, undefined otherwise + size_t messageLength; +}; + +/// \brief Interface for retrieving values given their names +/// \details This class is used to safely pass a variable number of arbitrarily +/// typed arguments to functions and to read values from keys and crypto parameters. +/// \details To obtain an object that implements NameValuePairs for the purpose of +/// parameter passing, use the MakeParameters() function. +/// \details To get a value from NameValuePairs, you need to know the name and the +/// type of the value. Call GetValueNames() on a NameValuePairs object to obtain a +/// list of value names that it supports. then look at the Name namespace +/// documentation to see what the type of each value is, or alternatively, call +/// GetIntValue() with the value name, and if the type is not int, a +/// ValueTypeMismatch exception will be thrown and you can get the actual type from +/// the exception object. +/// \sa NullNameValuePairs, g_nullNameValuePairs, +/// NameValuePairs on the +/// Crypto++ wiki +class NameValuePairs +{ +public: + virtual ~NameValuePairs() {} + + /// \brief Thrown when an unexpected type is encountered + /// \details Exception thrown when trying to retrieve a value using a different + /// type than expected + class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument + { + public: + /// \brief Construct a ValueTypeMismatch + /// \param name the name of the value + /// \param stored the \a actual type of the value stored + /// \param retrieving the \a presumed type of the value retrieved + ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving) + : InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'") + , m_stored(stored), m_retrieving(retrieving) {} + + /// \brief Provides the stored type + /// \return the C++ mangled name of the type + const std::type_info & GetStoredTypeInfo() const {return m_stored;} + + /// \brief Provides the retrieveing type + /// \return the C++ mangled name of the type + const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;} + + private: + const std::type_info &m_stored; + const std::type_info &m_retrieving; + }; + + /// \brief Get a copy of this object or subobject + /// \tparam T class or type + /// \param object reference to a variable that receives the value + template + bool GetThisObject(T &object) const + { + return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object); + } + + /// \brief Get a pointer to this object + /// \tparam T class or type + /// \param ptr reference to a pointer to a variable that receives the value + template + bool GetThisPointer(T *&ptr) const + { + return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), ptr); + } + + /// \brief Get a named value + /// \tparam T class or type + /// \param name the name of the object or value to retrieve + /// \param value reference to a variable that receives the value + /// \return true if the value was retrieved, false otherwise + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + template + bool GetValue(const char *name, T &value) const + { + return GetVoidValue(name, typeid(T), &value); + } + + /// \brief Get a named value + /// \tparam T class or type + /// \param name the name of the object or value to retrieve + /// \param defaultValue the default value of the class or type if it does not exist + /// \return the object or value + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + template + T GetValueWithDefault(const char *name, T defaultValue) const + { + T value; + bool result = GetValue(name, value); + // No assert... this recovers from failure + if (result) {return value;} + return defaultValue; + } + + /// \brief Get a list of value names that can be retrieved + /// \return a list of names available to retrieve + /// \details the items in the list are delimited with a colon. + CRYPTOPP_DLL std::string GetValueNames() const + {std::string result; GetValue("ValueNames", result); return result;} + + /// \brief Get a named value with type int + /// \param name the name of the value to retrieve + /// \param value the value retrieved upon success + /// \return true if an int value was retrieved, false otherwise + /// \details GetIntValue() is used to ensure we don't accidentally try to get an + /// unsigned int or some other type when we mean int (which is the most common case) + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const + {return GetValue(name, value);} + + /// \brief Get a named value with type int, with default + /// \param name the name of the value to retrieve + /// \param defaultValue the default value if the name does not exist + /// \return the value retrieved on success or the default value + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const + {return GetValueWithDefault(name, defaultValue);} + + /// \brief Get a named value with type word64 + /// \param name the name of the value to retrieve + /// \param value the value retrieved upon success + /// \return true if an word64 value was retrieved, false otherwise + /// \sa GetValue(), GetValueWithDefault(), GetWord64ValueWithDefault(), GetIntValue(), + /// GetIntValueWithDefault(), GetRequiredParameter() and GetRequiredIntParameter() + CRYPTOPP_DLL bool GetWord64Value(const char *name, word64 &value) const + {return GetValue(name, value);} + + /// \brief Get a named value with type word64, with default + /// \param name the name of the value to retrieve + /// \param defaultValue the default value if the name does not exist + /// \return the value retrieved on success or the default value + /// \sa GetValue(), GetValueWithDefault(), GetWord64Value(), GetIntValue(), + /// GetIntValueWithDefault(), GetRequiredParameter() and GetRequiredWord64Parameter() + CRYPTOPP_DLL word64 GetWord64ValueWithDefault(const char *name, word64 defaultValue) const + {return GetValueWithDefault(name, defaultValue);} + + /// \brief Ensures an expected name and type is present + /// \param name the name of the value + /// \param stored the type that was stored for the name + /// \param retrieving the type that is being retrieved for the name + /// \throw ValueTypeMismatch + /// \details ThrowIfTypeMismatch() effectively performs a type safety check. + /// stored and retrieving are C++ mangled names for the type. + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + CRYPTOPP_DLL static void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving) + {if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);} + + /// \brief Retrieves a required name/value pair + /// \tparam T class or type + /// \param className the name of the class + /// \param name the name of the value + /// \param value reference to a variable to receive the value + /// \throw InvalidArgument + /// \details GetRequiredParameter() throws InvalidArgument if the name + /// is not present or not of the expected type T. + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + template + void GetRequiredParameter(const char *className, const char *name, T &value) const + { + if (!GetValue(name, value)) + throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); + } + + /// \brief Retrieves a required name/value pair + /// \param className the name of the class + /// \param name the name of the value + /// \param value reference to a variable to receive the value + /// \throw InvalidArgument + /// \details GetRequiredParameter() throws InvalidArgument if the name + /// is not present or not of the expected type T. + /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(), + /// GetRequiredParameter() and GetRequiredIntParameter() + CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const + { + if (!GetIntValue(name, value)) + throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); + } + + /// \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() + CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0; +}; + +// Doxygen cannot handle initialization +#if CRYPTOPP_DOXYGEN_PROCESSING +/// \brief Default channel for BufferedTransformation +/// \details DEFAULT_CHANNEL is equal to an empty string +/// \details The definition for DEFAULT_CHANNEL is in cryptlib.cpp. +/// It can be subject to Static +/// Initialization Order Fiasco. If you experience a crash in +/// DEFAULT_CHANNEL where the string object is NULL, then you probably have +/// a global object using DEFAULT_CHANNEL before it has been constructed. +const std::string DEFAULT_CHANNEL; + +/// \brief Channel for additional authenticated data +/// \details AAD_CHANNEL is equal to "AAD" +/// \details The definition for AAD_CHANNEL is in cryptlib.cpp. +/// It can be subject to Static +/// Initialization Order Fiasco. If you experience a crash in +/// AAD_CHANNEL where the string object is NULL, then you probably have a +/// global object using AAD_CHANNEL before it has been constructed. +const std::string AAD_CHANNEL; + +/// \brief An empty set of name-value pairs +/// \details The definition for g_nullNameValuePairs is in cryptlib.cpp. +/// It can be subject to Static +/// Initialization Order Fiasco. If you experience a crash in +/// g_nullNameValuePairs where the string object is NULL, then you probably +/// have a global object using g_nullNameValuePairs before it has been +/// constructed. +const NameValuePairs& g_nullNameValuePairs; + +#else +extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL; +extern CRYPTOPP_DLL const std::string AAD_CHANNEL; +extern CRYPTOPP_DLL const NameValuePairs& g_nullNameValuePairs; +#endif + +// Document additional name spaces which show up elsewhere in the sources. +#if CRYPTOPP_DOXYGEN_PROCESSING +/// \brief Namespace containing value name definitions. +/// \details Name is part of the CryptoPP namespace. +/// \details The semantics of value names, types are: +///

+///     ThisObject:ClassName (ClassName, copy of this object or a subobject)
+///     ThisPointer:ClassName (const ClassName *, pointer to this object or a subobject)
+/// 
+DOCUMENTED_NAMESPACE_BEGIN(Name) +// more names defined in argnames.h +DOCUMENTED_NAMESPACE_END + +/// \brief Namespace containing weak and wounded algorithms. +/// \details Weak is part of the CryptoPP namespace. Schemes and algorithms are moved into Weak +/// when their security level is reduced to an unacceptable level by contemporary standards. +/// \details To use an algorithm in the Weak namespace, you must \c \#define +/// CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 before including a header for a weak or wounded +/// algorithm. For example: +///
  \c \#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
+///   \c \#include 
+///   ...
+///   CryptoPP::Weak::MD5 md5;
+///   
+DOCUMENTED_NAMESPACE_BEGIN(Weak) +// weak and wounded algorithms +DOCUMENTED_NAMESPACE_END +#endif + +/// \brief Namespace containing NaCl library functions +/// \details TweetNaCl is a compact and portable reimplementation of the NaCl library. +DOCUMENTED_NAMESPACE_BEGIN(NaCl) +// crypto_box, crypto_box_open, crypto_sign, and crypto_sign_open (and friends) +DOCUMENTED_NAMESPACE_END + +/// \brief Namespace containing testing and benchmark classes. +/// \details Source files for classes in the Test namespaces include +/// test.cpp, validat#.cpp and bench#.cpp. +DOCUMENTED_NAMESPACE_BEGIN(Test) +// testing and benchmark classes +DOCUMENTED_NAMESPACE_END + +// ******************************************************** + +/// \brief Interface for cloning objects +/// \note this is \a not implemented by most classes +/// \sa ClonableImpl, NotCopyable +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable +{ +public: + virtual ~Clonable() {} + + /// \brief Copies this object + /// \return a copy of this object + /// \throw NotImplemented + /// \note this is \a not implemented by most classes + /// \sa NotCopyable + virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");} // TODO: make this =0 +}; + +/// \brief Interface for all crypto algorithms +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable +{ +public: + virtual ~Algorithm() {} + + /// \brief Interface for all crypto algorithms + /// \param checkSelfTestStatus determines whether the object can proceed if the self + /// tests have not been run or failed. + /// \details When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true, + /// this constructor throws SelfTestFailure if the self test hasn't been run or fails. + /// \details FIPS 140-2 compliance is disabled by default. It is only used by certain + /// versions of the library when the library is built as a DLL on Windows. Also see + /// CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 in config.h. + Algorithm(bool checkSelfTestStatus = true); + + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + /// \details The standard algorithm name can be a name like AES or 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. + virtual std::string AlgorithmName() const {return "unknown";} + + /// \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). + /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". + /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics + /// instead of ASM. + /// \details Algorithms which combine different instructions or ISAs provide the + /// dominant one. For example on x86 AES/GCM returns "AESNI" rather than + /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". + /// \note Provider is not universally implemented yet. + /// \since Crypto++ 8.0 + virtual std::string AlgorithmProvider() const {return "C++";} +}; + +/// \brief Interface for algorithms that take byte strings as keys +/// \sa FixedKeyLength(), VariableKeyLength(), SameKeyLengthAs(), SimpleKeyingInterfaceImpl() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface +{ +public: + virtual ~SimpleKeyingInterface() {} + + /// \brief Returns smallest valid key length + /// \return the minimum key length, in bytes + virtual size_t MinKeyLength() const =0; + + /// \brief Returns largest valid key length + /// \return the maximum key length, in bytes + virtual size_t MaxKeyLength() const =0; + + /// \brief Returns default key length + /// \return the default key length, in bytes + virtual size_t DefaultKeyLength() const =0; + + /// \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. + virtual size_t GetValidKeyLength(size_t keylength) const =0; + + /// \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() + virtual bool IsValidKeyLength(size_t keylength) const + {return keylength == GetValidKeyLength(keylength);} + + /// \brief Sets or reset the key of this object + /// \param key the key to use when keying the object + /// \param length the size of the key, in bytes + /// \param params additional initialization parameters to configure this object + virtual void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs); + + /// \brief Sets or reset the key of this object + /// \param key the key to use when keying the object + /// \param length the size of the key, in bytes + /// \param rounds the number of rounds to apply the transformation function, + /// if applicable + /// \details SetKeyWithRounds() calls SetKey() with a NameValuePairs + /// object that only specifies rounds. rounds is an integer parameter, + /// and -1 means use the default number of rounds. + void SetKeyWithRounds(const byte *key, size_t length, int rounds); + + /// \brief Sets or reset the key of this object + /// \param key the key to use when keying the object + /// \param length the size of the key, in bytes + /// \param iv the initialization vector to use when keying the object + /// \param ivLength the size of the iv, in bytes + /// \details SetKeyWithIV() calls SetKey() with a NameValuePairs + /// that only specifies IV. The IV is a byte buffer with size ivLength. + /// ivLength is an integer parameter, and -1 means use IVSize(). + void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength); + + /// \brief Sets or reset the key of this object + /// \param key the key to use when keying the object + /// \param length the size of the key, in bytes + /// \param iv the initialization vector to use when keying the object + /// \details SetKeyWithIV() calls SetKey() with a NameValuePairs() object + /// that only specifies iv. iv is a byte buffer, and it must have + /// a size IVSize(). + void SetKeyWithIV(const byte *key, size_t length, const byte *iv) + {SetKeyWithIV(key, length, iv, IVSize());} + + /// \brief Secure IVs requirements as enumerated values. + /// \details Provides secure IV requirements as a monotonically increasing enumerated values. + /// Requirements can be compared using less than (<) and greater than (>). For example, + /// UNIQUE_IV < RANDOM_IV and UNPREDICTABLE_RANDOM_IV > RANDOM_IV. + /// \details Objects that use SimpleKeyingInterface do not support an optional IV. That is, + /// an IV must be present or it must be absent. If you wish to support an optional IV then + /// provide two classes - one with an IV and one without an IV. + /// \sa IsResynchronizable(), CanUseRandomIVs(), CanUsePredictableIVs(), CanUseStructuredIVs() + enum IV_Requirement { + /// \brief The IV must be unique + UNIQUE_IV = 0, + /// \brief The IV must be random and possibly predictable + RANDOM_IV, + /// \brief The IV must be random and unpredictable + UNPREDICTABLE_RANDOM_IV, + /// \brief The IV is set by the object + INTERNALLY_GENERATED_IV, + /// \brief The object does not use an IV + NOT_RESYNCHRONIZABLE + }; + + /// \brief Minimal requirement for secure IVs + /// \return the secure IV requirement of the algorithm + virtual IV_Requirement IVRequirement() const =0; + + /// \brief Determines if the object can be resynchronized + /// \return true if the object can be resynchronized (i.e. supports initialization vectors), false otherwise + /// \note If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, + /// an IV of all 0's will be assumed. + bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;} + + /// \brief Determines if the object can use random IVs + /// \return true if the object can use random IVs (in addition to ones returned by GetNextIV), false otherwise + bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;} + + /// \brief Determines if the object can use random but possibly predictable IVs + /// \return true if the object can use random but possibly predictable IVs (in addition to ones returned by + /// GetNextIV), false otherwise + bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;} + + /// \brief Determines if the object can use structured IVs + /// \return true if the object can use structured IVs, false otherwise + /// \details CanUseStructuredIVs() indicates whether the object can use structured IVs; for example a counter + /// (in addition to ones returned by GetNextIV). + bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;} + + /// \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 + virtual unsigned int IVSize() const + {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");} + + /// \brief Provides the default size of an IV + /// \return default length of IVs accepted by this object, in bytes + unsigned int DefaultIVLength() const {return IVSize();} + + /// \brief Provides the minimum size of an IV + /// \return minimal length of IVs accepted by this object, in bytes + /// \throw NotImplemented() if the object does not support resynchronization + virtual unsigned int MinIVLength() const {return IVSize();} + + /// \brief Provides the maximum size of an IV + /// \return maximal length of IVs accepted by this object, in bytes + /// \throw NotImplemented() if the object does not support resynchronization + virtual unsigned int MaxIVLength() const {return IVSize();} + + /// \brief Resynchronize with an IV + /// \param iv the initialization vector + /// \param ivLength the size of the initialization vector, in bytes + /// \details Resynchronize() resynchronizes with an IV provided by the caller. ivLength=-1 means use IVSize(). + /// \throw NotImplemented() if the object does not support resynchronization + virtual void Resynchronize(const byte *iv, int ivLength=-1) { + CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(ivLength); + throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization"); + } + + /// \brief Retrieves a secure IV for the next message + /// \param rng a RandomNumberGenerator to produce keying material + /// \param iv a block of bytes to receive the IV + /// \details The IV must be at least IVSize() in length. + /// \details This method should be called after you finish encrypting one message and are ready + /// to start the next one. After calling it, you must call SetKey() or Resynchronize(). + /// before using this object again. + /// \details Internally, the base class implementation calls RandomNumberGenerator's GenerateBlock() + /// \note This method is not implemented on decryption objects. + virtual void GetNextIV(RandomNumberGenerator &rng, byte *iv); + +protected: + /// \brief Returns the base class Algorithm + /// \return the base class Algorithm + virtual const Algorithm & GetAlgorithm() const =0; + + /// \brief Sets the key for this object without performing parameter validation + /// \param key a byte buffer used to key the cipher + /// \param length the length of the byte buffer + /// \param params additional parameters passed as NameValuePairs + /// \details key must be at least DEFAULT_KEYLENGTH in length. + virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) =0; + + /// \brief Validates the key length + /// \param length the size of the keying material, in bytes + /// \throw InvalidKeyLength if the key length is invalid + void ThrowIfInvalidKeyLength(size_t length); + + /// \brief Validates the object + /// \throw InvalidArgument if the IV is present + /// \details Internally, the default implementation calls IsResynchronizable() and throws + /// InvalidArgument if the function returns true. + /// \note called when no IV is passed + void ThrowIfResynchronizable(); + + /// \brief Validates the IV + /// \param iv the IV with a length of IVSize, in bytes + /// \throw InvalidArgument on failure + /// \details Internally, the default implementation checks the iv. If iv is not NULL or nullptr, + /// then the function succeeds. If iv is NULL, then IVRequirement is checked against + /// UNPREDICTABLE_RANDOM_IV. If IVRequirement is UNPREDICTABLE_RANDOM_IV, then + /// then the function succeeds. Otherwise, an exception is thrown. + void ThrowIfInvalidIV(const byte *iv); + + /// \brief Validates the IV length + /// \param length the size of an IV, in bytes + /// \throw InvalidArgument if the IV length is invalid + size_t ThrowIfInvalidIVLength(int length); + + /// \brief Retrieves and validates the IV + /// \param params NameValuePairs with the IV supplied as a ConstByteArrayParameter + /// \param size the length of the IV, in bytes + /// \return a pointer to the first byte of the IV + /// \throw InvalidArgument if the number of rounds are invalid + const byte * GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size); + + /// \brief Validates the key length + /// \param length the size of the keying material, in bytes + inline void AssertValidKeyLength(size_t length) const + {CRYPTOPP_UNUSED(length); CRYPTOPP_ASSERT(IsValidKeyLength(length));} +}; + +/// \brief Interface for the data processing part of block ciphers +/// \details Classes derived from BlockTransformation are block ciphers +/// in ECB mode (for example the DES::Encryption class), which are stateless. +/// These classes should not be used directly, but only in combination with +/// a mode class (see CipherModeDocumentation in modes.h). +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm +{ +public: + virtual ~BlockTransformation() {} + + /// \brief Encrypt or decrypt a block + /// \param inBlock the input message before processing + /// \param outBlock the output message after processing + /// \param xorBlock an optional XOR mask + /// \details ProcessAndXorBlock encrypts or decrypts inBlock, xor with xorBlock, and write to outBlock. + /// \details The size of the block is determined by the block cipher and its documentation. Use + /// BLOCKSIZE at compile time, or BlockSize() at runtime. + /// \note The message can be transformed in-place, or the buffers must \a not overlap + /// \sa FixedBlockSize, BlockCipherFinal from seckey.h and BlockSize() + virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0; + + /// \brief Encrypt or decrypt a block + /// \param inBlock the input message before processing + /// \param outBlock the output message after processing + /// \details ProcessBlock encrypts or decrypts inBlock and write to outBlock. + /// \details The size of the block is determined by the block cipher and its documentation. + /// Use BLOCKSIZE at compile time, or BlockSize() at runtime. + /// \sa FixedBlockSize, BlockCipherFinal from seckey.h and BlockSize() + /// \note The message can be transformed in-place, or the buffers must \a not overlap + void ProcessBlock(const byte *inBlock, byte *outBlock) const + {ProcessAndXorBlock(inBlock, NULLPTR, outBlock);} + + /// \brief Encrypt or decrypt a block in place + /// \param inoutBlock the input message before processing + /// \details ProcessBlock encrypts or decrypts inoutBlock in-place. + /// \details The size of the block is determined by the block cipher and its documentation. + /// Use BLOCKSIZE at compile time, or BlockSize() at runtime. + /// \sa FixedBlockSize, BlockCipherFinal from seckey.h and BlockSize() + void ProcessBlock(byte *inoutBlock) const + {ProcessAndXorBlock(inoutBlock, NULLPTR, inoutBlock);} + + /// Provides the block size of the cipher + /// \return the block size of the cipher, in bytes + virtual unsigned int BlockSize() const =0; + + /// \brief Provides input and output data alignment for optimal performance. + /// \return the input data alignment that provides optimal performance + /// \sa GetAlignment() and OptimalBlockSize() + virtual unsigned int OptimalDataAlignment() const; + + /// \brief Determines if the transformation is a permutation + /// \return true if this is a permutation (i.e. there is an inverse transformation) + virtual bool IsPermutation() const {return true;} + + /// \brief Determines if the cipher is being operated in its forward direction + /// \return true if DIR is ENCRYPTION, false otherwise + /// \sa IsForwardTransformation(), IsPermutation(), GetCipherDirection() + virtual bool IsForwardTransformation() const =0; + + /// \brief Determines the number of blocks that can be processed in parallel + /// \return the number of blocks that can be processed in parallel, for bit-slicing implementations + /// \details Bit-slicing is often used to improve throughput and minimize timing attacks. + virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;} + + /// \brief Bit flags that control AdvancedProcessBlocks() behavior + enum FlagsForAdvancedProcessBlocks { + /// \brief inBlock is a counter + BT_InBlockIsCounter=1, + /// \brief should not modify block pointers + BT_DontIncrementInOutPointers=2, + /// \brief Xor inputs before transformation + BT_XorInput=4, + /// \brief perform the transformation in reverse + BT_ReverseDirection=8, + /// \brief Allow parallel transformations + BT_AllowParallel=16}; + + /// \brief Encrypt and xor multiple blocks using additional flags + /// \param inBlocks the input message before processing + /// \param xorBlocks an optional XOR mask + /// \param outBlocks the output message after processing + /// \param length the size of the blocks, in bytes + /// \param flags additional flags to control processing + /// \details Encrypt and xor multiple blocks according to FlagsForAdvancedProcessBlocks flags. + /// \note If BT_InBlockIsCounter is set, then the last byte of inBlocks may be modified. + virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; + + /// \brief Provides the direction of the cipher + /// \return ENCRYPTION if IsForwardTransformation() is true, DECRYPTION otherwise + /// \sa IsForwardTransformation(), IsPermutation() + inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;} +}; + +/// \brief Interface for the data processing portion of stream ciphers +/// \sa StreamTransformationFilter() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm +{ +public: + virtual ~StreamTransformation() {} + + /// \brief Provides a reference to this object + /// \return A reference to this object + /// \details Useful for passing a temporary object to a function that takes a non-const reference + StreamTransformation& Ref() {return *this;} + + /// \brief Provides the mandatory block size of the cipher + /// \return The block size of the cipher if input must be processed in blocks, 1 otherwise + /// \details Stream ciphers and some block ciphers modes of operation return 1. Modes that + /// return 1 must be able to process a single byte at a time, like counter mode. If a + /// mode of operation or block cipher cannot stream then it must not return 1. + /// \details When filters operate the mode or cipher, ProcessData will be called with a + /// string of bytes that is determined by MandatoryBlockSize and OptimalBlockSize. When a + /// policy is set, like 16-byte strings for a 16-byte block cipher, the filter will buffer + /// bytes until the specified number of bytes is available to the object. + /// \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial + virtual unsigned int MandatoryBlockSize() const {return 1;} + + /// \brief Provides the input block size most efficient for this cipher + /// \return The input block size that is most efficient for the cipher + /// \details The base class implementation returns MandatoryBlockSize(). + /// \note Optimal input length is + /// n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n \> 0. + virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();} + + /// \brief Provides the number of bytes used in the current block when processing at optimal block size. + /// \return the number of bytes used in the current block when processing at the optimal block size + virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;} + + /// \brief Provides input and output data alignment for optimal performance + /// \return the input data alignment that provides optimal performance + /// \sa GetAlignment() and OptimalBlockSize() + virtual unsigned int OptimalDataAlignment() const; + + /// \brief Encrypt or decrypt an array of bytes + /// \param outString the output byte buffer + /// \param inString the input byte buffer + /// \param length the size of the input and output byte buffers, in bytes + /// \details ProcessData is called with a string of bytes whose size depends on MandatoryBlockSize. + /// Either inString == outString, or they must not overlap. + /// \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial + virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0; + + /// \brief Encrypt or decrypt the last block of data + /// \param outString the output byte buffer + /// \param outLength the size of the output byte buffer, in bytes + /// \param inString the input byte buffer + /// \param inLength the size of the input byte buffer, in bytes + /// \return the number of bytes used in outString + /// \details ProcessLastBlock is used when the last block of data is special and requires handling + /// by the cipher. The current implementation provides an output buffer with a size + /// inLength+2*MandatoryBlockSize(). The return value allows the cipher to expand cipher + /// text during encryption or shrink plain text during decryption. + /// \details This member function is used by CBC-CTS and OCB modes. + /// \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial + virtual size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); + + /// \brief Provides the size of the last block + /// \return the minimum size of the last block + /// \details MinLastBlockSize() returns the minimum size of the last block. 0 indicates the last + /// block is not special. + /// \details MandatoryBlockSize() enlists one of two behaviors. First, if MandatoryBlockSize() + /// returns 1, then the cipher can be streamed and ProcessData() is called with the tail bytes. + /// Second, if MandatoryBlockSize() returns non-0, then the string of bytes is padded to + /// MandatoryBlockSize() according to the padding mode. Then, ProcessData() is called with the + /// padded string of bytes. + /// \details Some authenticated encryption modes are not expressed well with MandatoryBlockSize() + /// and MinLastBlockSize(). For example, AES/OCB uses 16-byte blocks (MandatoryBlockSize = 16) + /// and the last block requires special processing (MinLastBlockSize = 0). However, 0 is a valid + /// last block size for OCB and the special processing is custom padding, and not standard PKCS + /// padding. In response an unambiguous IsLastBlockSpecial() was added. + /// \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial + virtual unsigned int MinLastBlockSize() const {return 0;} + + /// \brief Determines if the last block receives special processing + /// \return true if the last block receives special processing, false otherwise. + /// \details Some authenticated encryption modes are not expressed well with + /// MandatoryBlockSize() and MinLastBlockSize(). For example, AES/OCB uses + /// 16-byte blocks (MandatoryBlockSize = 16) and the last block requires special processing + /// (MinLastBlockSize = 0). However, 0 is a valid last block size for OCB and the special + /// processing is custom padding, and not standard PKCS padding. In response an + /// unambiguous IsLastBlockSpecial() was added. + /// \details When IsLastBlockSpecial() returns false nothing special happens. All the former + /// rules and behaviors apply. This is the default behavior of IsLastBlockSpecial(). + /// \details When IsLastBlockSpecial() returns true four things happen. First, MinLastBlockSize = 0 + /// means 0 is a valid block size that should be processed. Second, standard block cipher padding is + /// \a not \a applied. Third, the caller supplies an outString is larger than inString by + /// 2*MandatoryBlockSize(). That is, there's a reserve available when processing the last block. + /// Fourth, the cipher is responsible for finalization like custom padding. The cipher will tell + /// the library how many bytes were processed or used by returning the appropriate value from + /// ProcessLastBlock(). + /// \details The return value of ProcessLastBlock() indicates how many bytes were written to + /// outString. A filter pipelining data will send outString and up to outLength + /// to an AttachedTransformation() for additional processing. Below is an example of the code + /// used in StreamTransformationFilter::LastPut. + ///
  if (m_cipher.IsLastBlockSpecial())
+	///   {
+	///     size_t reserve = 2*m_cipher.MandatoryBlockSize();
+	///     space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length+reserve);
+	///     length = m_cipher.ProcessLastBlock(space, length+reserve, inString, length);
+	///     AttachedTransformation()->Put(space, length);
+	///     return;
+	///   }
+ /// \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial + /// \since Crypto++ 6.0 + virtual bool IsLastBlockSpecial() const {return false;} + + /// \brief Encrypt or decrypt a string of bytes + /// \param inoutString the string to process + /// \param length the size of the inoutString, in bytes + /// \details Internally, the base class implementation calls ProcessData(). + inline void ProcessString(byte *inoutString, size_t length) + {ProcessData(inoutString, inoutString, length);} + + /// \brief Encrypt or decrypt a string of bytes + /// \param outString the output string to process + /// \param inString the input string to process + /// \param length the size of the input and output strings, in bytes + /// \details Internally, the base class implementation calls ProcessData(). + inline void ProcessString(byte *outString, const byte *inString, size_t length) + {ProcessData(outString, inString, length);} + + /// \brief Encrypt or decrypt a byte + /// \param input the input byte to process + /// \details Internally, the base class implementation calls ProcessData() with a size of 1. + inline byte ProcessByte(byte input) + {ProcessData(&input, &input, 1); return input;} + + /// \brief Determines whether the cipher supports random access + /// \return true if the cipher supports random access, false otherwise + virtual bool IsRandomAccess() const =0; + + /// \brief Seek to an absolute position + /// \param pos position to seek + /// \throw NotImplemented + /// \details The base class implementation throws NotImplemented. The function + /// \ref CRYPTOPP_ASSERT "asserts" IsRandomAccess() in debug builds. + virtual void Seek(lword pos) + { + CRYPTOPP_UNUSED(pos); + CRYPTOPP_ASSERT(!IsRandomAccess()); + throw NotImplemented("StreamTransformation: this object doesn't support random access"); + } + + /// \brief Determines whether the cipher is self-inverting + /// \return true if the cipher is self-inverting, false otherwise + /// \details IsSelfInverting determines whether this transformation is + /// self-inverting (e.g. xor with a keystream). + virtual bool IsSelfInverting() const =0; + + /// \brief Determines if the cipher is being operated in its forward direction + /// \return true if DIR is ENCRYPTION, false otherwise + /// \sa IsForwardTransformation(), IsPermutation(), GetCipherDirection() + virtual bool IsForwardTransformation() const =0; +}; + +/// \brief Interface for hash functions and data processing part of MACs +/// \details HashTransformation objects are stateful. They are created in an initial state, +/// change state as Update() is called, and return to the initial +/// state when Final() is called. This interface allows a large message to +/// be hashed in pieces by calling Update() on each piece followed by +/// calling Final(). +/// \sa HashFilter(), HashVerificationFilter() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm +{ +public: + virtual ~HashTransformation() {} + + /// \brief Provides a reference to this object + /// \return A reference to this object + /// \details Useful for passing a temporary object to a function that takes a non-const reference + HashTransformation& Ref() {return *this;} + + /// \brief Updates a hash with additional input + /// \param input the additional input as a buffer + /// \param length the size of the buffer, in bytes + virtual void Update(const byte *input, size_t length) =0; + + /// \brief Request space which can be written into by the caller + /// \param size the requested size of the buffer + /// \details The purpose of this method is to help avoid extra memory allocations. + /// \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made, + /// size is the requested size of the buffer. When the call returns, size is the size of + /// the array returned to the caller. + /// \details The base class implementation sets size to 0 and returns NULL or nullptr. + /// \note Some objects, like ArraySink, cannot create a space because its fixed. + virtual byte * CreateUpdateSpace(size_t &size) {size=0; return NULLPTR;} + + /// \brief Computes the hash of the current message + /// \param digest a pointer to the buffer to receive the hash + /// \details Final() restarts the hash for a new message. + /// \pre COUNTOF(digest) <= DigestSize() or COUNTOF(digest) <= HASH::DIGESTSIZE ensures + /// the output byte buffer is large enough for the digest. + virtual void Final(byte *digest) + {TruncatedFinal(digest, DigestSize());} + + /// \brief Restart the hash + /// \details Discards the current state, and restart for a new message + virtual void Restart() + {TruncatedFinal(NULLPTR, 0);} + + /// Provides the digest size of the hash + /// \return the digest size of the hash. + virtual unsigned int DigestSize() const =0; + + /// Provides the tag size of the hash + /// \return the tag size of the hash. + /// \details Same as DigestSize(). + unsigned int TagSize() const {return 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 r. + virtual unsigned int BlockSize() const {return 0;} + + /// \brief Provides the input block size most efficient for this hash. + /// \return The input block size that is most efficient for the cipher + /// \details The base class implementation returns MandatoryBlockSize(). + /// \details Optimal input length is + /// n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n \> 0. + virtual unsigned int OptimalBlockSize() const {return 1;} + + /// \brief Provides input and output data alignment for optimal performance + /// \return the input data alignment that provides optimal performance + /// \sa GetAlignment() and OptimalBlockSize() + virtual unsigned int OptimalDataAlignment() const; + + /// \brief Updates the hash with additional input and computes the hash of the current message + /// \param digest a pointer to the buffer to receive the hash + /// \param input the additional input as a buffer + /// \param length the size of the buffer, in bytes + /// \details Use this if your input is in one piece and you don't want to call Update() + /// and Final() separately + /// \details CalculateDigest() restarts the hash for the next message. + /// \pre COUNTOF(digest) == DigestSize() or COUNTOF(digest) == HASH::DIGESTSIZE ensures + /// the output byte buffer is a valid size. + virtual void CalculateDigest(byte *digest, const byte *input, size_t length) + {Update(input, length); Final(digest);} + + /// \brief Verifies the hash of the current message + /// \param digest a pointer to the buffer of an \a existing hash + /// \return \p true if the existing hash matches the computed hash, \p false otherwise + /// \throw InvalidArgument() if the existing hash's size exceeds DigestSize() + /// \details Verify() performs a bitwise compare on the buffers using VerifyBufsEqual(), which is + /// a constant time comparison function. digestLength cannot exceed DigestSize(). + /// \details Verify() restarts the hash for the next message. + /// \pre COUNTOF(digest) == DigestSize() or COUNTOF(digest) == HASH::DIGESTSIZE ensures + /// the input byte buffer is a valid size. + virtual bool Verify(const byte *digest) + {return TruncatedVerify(digest, DigestSize());} + + /// \brief Updates the hash with additional input and verifies the hash of the current message + /// \param digest a pointer to the buffer of an \a existing hash + /// \param input the additional input as a buffer + /// \param length the size of the buffer, in bytes + /// \return \p true if the existing hash matches the computed hash, \p false otherwise + /// \throw InvalidArgument() if the existing hash's size exceeds DigestSize() + /// \details Use this if your input is in one piece and you don't want to call Update() + /// and Verify() separately + /// \details VerifyDigest() performs a bitwise compare on the buffers using VerifyBufsEqual(), + /// which is a constant time comparison function. + /// \details VerifyDigest() restarts the hash for the next message. + /// \pre COUNTOF(digest) == DigestSize() or COUNTOF(digest) == HASH::DIGESTSIZE ensures + /// the output byte buffer is a valid size. + virtual bool VerifyDigest(const byte *digest, const byte *input, size_t length) + {Update(input, length); return Verify(digest);} + + /// \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() calls Final() and then copies digestSize bytes to digest. + /// The hash is restarted the hash for the next message. + /// \pre COUNTOF(digest) <= DigestSize() or COUNTOF(digest) <= HASH::DIGESTSIZE ensures + /// the output byte buffer is a valid size. + virtual void TruncatedFinal(byte *digest, size_t digestSize) =0; + + /// \brief Updates the hash with additional input and computes the hash of the current message + /// \param digest a pointer to the buffer to receive the hash + /// \param digestSize the length of the truncated hash, in bytes + /// \param input the additional input as a buffer + /// \param length the size of the buffer, in bytes + /// \details Use this if your input is in one piece and you don't want to call Update() + /// and CalculateDigest() separately. + /// \details CalculateTruncatedDigest() restarts the hash for the next message. + /// \pre digestSize <= DigestSize() or digestSize <= HASH::DIGESTSIZE ensures + /// the output byte buffer is a valid size. + virtual void CalculateTruncatedDigest(byte *digest, size_t digestSize, const byte *input, size_t length) + {Update(input, length); TruncatedFinal(digest, digestSize);} + + /// \brief Verifies the hash of the current message + /// \param digest a pointer to the buffer of an \a existing hash + /// \param digestLength the size of the truncated hash, in bytes + /// \return \p true if the existing hash matches the computed hash, \p false otherwise + /// \throw InvalidArgument() if digestLength exceeds DigestSize() + /// \details TruncatedVerify() is a truncated version of Verify(). It can operate on a + /// buffer smaller than DigestSize(). However, digestLength cannot exceed DigestSize(). + /// \details Verify() performs a bitwise compare on the buffers using VerifyBufsEqual(), which is + /// a constant time comparison function. digestLength cannot exceed DigestSize(). + /// \details TruncatedVerify() restarts the hash for the next message. + /// \pre digestLength <= DigestSize() or digestLength <= HASH::DIGESTSIZE ensures + /// the input byte buffer is a valid size. + virtual bool TruncatedVerify(const byte *digest, size_t digestLength); + + /// \brief Updates the hash with additional input and verifies the hash of the current message + /// \param digest a pointer to the buffer of an \a existing hash + /// \param digestLength the size of the truncated hash, in bytes + /// \param input the additional input as a buffer + /// \param length the size of the buffer, in bytes + /// \return \p true if the existing hash matches the computed hash, \p false otherwise + /// \throw InvalidArgument() if digestLength exceeds DigestSize() + /// \details Use this if your input is in one piece and you don't want to call Update() + /// and TruncatedVerify() separately. + /// \details VerifyTruncatedDigest() is a truncated version of VerifyDigest(). It can operate + /// on a buffer smaller than DigestSize(). However, digestLength cannot exceed DigestSize(). + /// \details VerifyTruncatedDigest() restarts the hash for the next message. + /// \pre digestLength <= DigestSize() or digestLength <= HASH::DIGESTSIZE ensures + /// the input byte buffer is a valid size. + virtual bool VerifyTruncatedDigest(const byte *digest, size_t digestLength, const byte *input, size_t length) + {Update(input, length); return TruncatedVerify(digest, digestLength);} + +protected: + /// \brief Validates a truncated digest size + /// \param size the requested digest size + /// \throw InvalidArgument if the algorithm's digest size cannot be truncated to the requested size + /// \details Throws an exception when the truncated digest size is greater than DigestSize() + void ThrowIfInvalidTruncatedSize(size_t size) const; +}; + +/// \brief Interface for one direction (encryption or decryption) of a block cipher +/// \details These objects usually should not be used directly. See BlockTransformation for more details. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation +{ +protected: + const Algorithm & GetAlgorithm() const {return *this;} +}; + +/// \brief Interface for one direction (encryption or decryption) of a stream cipher or cipher mode +/// \details These objects usually should not be used directly. See StreamTransformation for more details. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation +{ +protected: + const Algorithm & GetAlgorithm() const {return *this;} +}; + +/// \brief Interface for message authentication codes +/// \details These objects usually should not be used directly. See HashTransformation for more details. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation +{ +protected: + const Algorithm & GetAlgorithm() const {return *this;} +}; + +/// \brief Interface for authenticated encryption modes of operation +/// \details AuthenticatedSymmetricCipher() provides the interface for one direction +/// (encryption or decryption) of a stream cipher or block cipher mode with authentication. The +/// StreamTransformation() part of this interface is used to encrypt or decrypt the data. The +/// MessageAuthenticationCode() part of the interface is used to input additional authenticated +/// data (AAD), which is MAC'ed but not encrypted. The MessageAuthenticationCode() part is also +/// used to generate and verify the MAC. +/// \details Crypto++ provides four authenticated encryption modes of operation - CCM, EAX, GCM +/// and OCB mode. All modes implement AuthenticatedSymmetricCipher() and the motivation for +/// the API, like calling AAD a "header", can be found in Bellare, Rogaway and +/// Wagner's The EAX Mode of +/// Operation. The EAX paper suggested a basic API to help standardize AEAD schemes in +/// software and promote adoption of the modes. +/// \sa Authenticated +/// Encryption on the Crypto++ wiki. +/// \since Crypto++ 5.6.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation +{ +public: + virtual ~AuthenticatedSymmetricCipher() {} + + /// \brief Exception thrown when the object is in the wrong state for the operation + /// \details this indicates that a member function was called in the wrong state, for example trying to encrypt + /// a message before having set the key or IV + class BadState : public Exception + { + public: + explicit BadState(const std::string &name, const char *message) : Exception(OTHER_ERROR, name + ": " + message) {} + explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {} + }; + + /// \brief Provides the maximum length of AAD that can be input + /// \return the maximum length of AAD that can be input before the encrypted data + virtual lword MaxHeaderLength() const =0; + + /// \brief Provides the maximum length of encrypted data + /// \return the maximum length of encrypted data + virtual lword MaxMessageLength() const =0; + + /// \brief Provides the maximum length of AAD + /// \return the maximum length of AAD that can be input after the encrypted data + virtual lword MaxFooterLength() const {return 0;} + + /// \brief Determines if data lengths must be specified prior to inputting data + /// \return true if the data lengths are required before inputting data, false otherwise + /// \details if this function returns true, SpecifyDataLengths() must be called before attempting to input data. + /// This is the case for some schemes, such as CCM. + /// \sa SpecifyDataLengths() + virtual bool NeedsPrespecifiedDataLengths() const {return false;} + + /// \brief Prescribes the data lengths + /// \param headerLength size of data before message is input, in bytes + /// \param messageLength size of the message, in bytes + /// \param footerLength size of data after message is input, in bytes + /// \details SpecifyDataLengths() only needs to be called if NeedsPrespecifiedDataLengths() returns true. + /// If true, then headerLength will be validated against MaxHeaderLength(), + /// messageLength will be validated against MaxMessageLength(), and + /// footerLength will be validated against MaxFooterLength(). + /// \sa NeedsPrespecifiedDataLengths() + void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=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 header the AAD buffer + /// \param headerLength 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 macSize < TagSize(). + virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, 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 header the AAD buffer + /// \param headerLength the size of the AAD buffer, in bytes + /// \param ciphertext the ciphertext 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. + /// message 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 macLength < TagSize(). + virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength); + + /// \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. + virtual std::string AlgorithmName() const; + + /// \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). + /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". + /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics + /// instead of ASM. + /// \details Algorithms which combine different instructions or ISAs provide the + /// dominant one. For example on x86 AES/GCM returns "AESNI" rather than + /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". + /// \note Provider is not universally implemented yet. + /// \since Crypto++ 8.0 + virtual std::string AlgorithmProvider() const {return "C++";} + +protected: + const Algorithm & GetAlgorithm() const + {return *static_cast(this);} + virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) + {CRYPTOPP_UNUSED(headerLength); CRYPTOPP_UNUSED(messageLength); CRYPTOPP_UNUSED(footerLength);} +}; + +/// \brief Interface for random number generators +/// \details The library provides a number of random number generators, from software based +/// to hardware based generators. +/// \details All generated values are uniformly distributed over the range specified. +/// \since Crypto++ 3.1 +/// \sa RandomNumberGenerator +/// on the Crypto++ wiki +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm +{ +public: + virtual ~RandomNumberGenerator() {} + + /// \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 + /// \throw NotImplemented + /// \details A generator may or may not accept additional entropy. Call CanIncorporateEntropy() + /// to test for the ability to use additional entropy. + /// \details If a derived class does not override IncorporateEntropy(), then the base class + /// throws NotImplemented. + virtual void IncorporateEntropy(const byte *input, size_t length) + { + CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length); + throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented"); + } + + /// \brief Determines if a generator can accept additional entropy + /// \return true if IncorporateEntropy() is implemented + virtual bool CanIncorporateEntropy() const {return false;} + + /// \brief Generate new random byte and return it + /// \return a random 8-bit byte + /// \details Default implementation calls GenerateBlock() with one byte. + /// \details All generated values are uniformly distributed over the range specified within the + /// the constraints of a particular generator. + virtual byte GenerateByte(); + + /// \brief Generate new random bit and return it + /// \return a random bit + /// \details The default implementation calls GenerateByte() and return its lowest bit. + /// \details All generated values are uniformly distributed over the range specified within the + /// the constraints of a particular generator. + virtual unsigned int GenerateBit(); + + /// \brief Generate a random 32 bit word in the range min to max, inclusive + /// \param min the lower bound of the range + /// \param max the upper bound of the range + /// \return a random 32-bit word + /// \details The default implementation calls Crop() on the difference between max and + /// min, and then returns the result added to min. + /// \details All generated values are uniformly distributed over the range specified within the + /// the constraints of a particular generator. + virtual word32 GenerateWord32(word32 min=0, word32 max=0xffffffffUL); + + /// \brief Generate random array of bytes + /// \param output the byte buffer + /// \param size the length of the buffer, in bytes + /// \details All generated values are uniformly distributed over the range specified within the + /// the constraints of a particular generator. + /// \note A derived generator \a must override either GenerateBlock() or + /// GenerateIntoBufferedTransformation(). They can override both, or have one call the other. + virtual void GenerateBlock(byte *output, size_t size); + + /// \brief Generate random bytes into a BufferedTransformation + /// \param target the BufferedTransformation object which receives the bytes + /// \param channel the channel on which the bytes should be pumped + /// \param length the number of bytes to generate + /// \details The default implementation calls GenerateBlock() and pumps the result into + /// the DEFAULT_CHANNEL of the target. + /// \details All generated values are uniformly distributed over the range specified within the + /// the constraints of a particular generator. + /// \note A derived generator \a must override either GenerateBlock() or + /// GenerateIntoBufferedTransformation(). They can override both, or have one call the other. + virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length); + + /// \brief Generate and discard n bytes + /// \param n the number of bytes to generate and discard + virtual void DiscardBytes(size_t n); + + /// \brief Randomly shuffle the specified array + /// \param begin an iterator to the first element in the array + /// \param end an iterator beyond the last element in the array + /// \details The resulting permutation is uniformly distributed. + template void Shuffle(IT begin, IT end) + { + // TODO: What happens if there are more than 2^32 elements? + for (; begin != end; ++begin) + std::iter_swap(begin, begin + GenerateWord32(0, static_cast(end-begin-1))); + } +}; + +/// \brief Interface for key derivation functions +/// \since Crypto++ 7.0 +/// \sa KeyDerivationFunction +/// on the Crypto++ wiki +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyDerivationFunction : public Algorithm +{ +public: + virtual ~KeyDerivationFunction() {} + + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + virtual std::string AlgorithmName() const =0; + + /// \brief Determine minimum number of bytes + /// \return Minimum number of bytes which can be derived + virtual size_t MinDerivedKeyLength() const; + + /// \brief Determine maximum number of bytes + /// \return Maximum number of bytes which can be derived + virtual size_t MaxDerivedKeyLength() const; + + /// \brief Returns a valid key length for the derivation function + /// \param keylength the size of the derived key, in bytes + /// \return the valid key length, in bytes + virtual size_t GetValidDerivedLength(size_t keylength) const =0; + + /// \brief Returns whether keylength is a valid key length + /// \param keylength the requested keylength + /// \return true if the derived keylength is valid, false otherwise + /// \details Internally the function calls GetValidKeyLength() + virtual bool IsValidDerivedLength(size_t keylength) const { + return keylength == GetValidDerivedLength(keylength); + } + + /// \brief Derive a key from a seed + /// \param derived the derived output buffer + /// \param derivedLen the size of the derived buffer, in bytes + /// \param secret the seed input buffer + /// \param secretLen the size of the secret buffer, in bytes + /// \param params additional initialization parameters to configure this object + /// \return the number of iterations performed + /// \throw InvalidDerivedKeyLength if derivedLen is invalid for the scheme + /// \details DeriveKey() provides a standard interface to derive a key from + /// a secret seed and other parameters. Each class that derives from KeyDerivationFunction + /// provides an overload that accepts most parameters used by the derivation function. + /// \details the number of iterations performed by DeriveKey() may be 1. For example, a + /// scheme like HKDF does not use the iteration count so it returns 1. + virtual size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs& params = g_nullNameValuePairs) const =0; + + /// \brief Set or change parameters + /// \param params additional initialization parameters to configure this object + /// \details SetParameters() is useful for setting common parameters when an object is + /// reused. Some derivation function classes may choose to implement it. + virtual void SetParameters(const NameValuePairs& params); + +protected: + /// \brief Returns the base class Algorithm + /// \return the base class Algorithm + virtual const Algorithm & GetAlgorithm() const =0; + + /// \brief Validates the derived key length + /// \param length the size of the derived key material, in bytes + /// \throw InvalidKeyLength if the key length is invalid + void ThrowIfInvalidDerivedKeyLength(size_t length) const; +}; + +/// \brief Interface for password based key derivation functions +/// \since Crypto++ 7.0 +struct PasswordBasedKeyDerivationFunction : public KeyDerivationFunction +{ +}; + +/// \brief Random Number Generator that does not produce random numbers +/// \return reference that can be passed to functions that require a RandomNumberGenerator +/// \details NullRNG() returns a reference that can be passed to functions that require a +/// RandomNumberGenerator but don't actually use it. The NullRNG() throws NotImplemented +/// when a generation function is called. +/// \sa ClassNullRNG, PK_SignatureScheme::IsProbabilistic() +CRYPTOPP_DLL RandomNumberGenerator & CRYPTOPP_API NullRNG(); + +class WaitObjectContainer; +class CallStack; + +/// \brief Interface for objects that can be waited on. +class CRYPTOPP_NO_VTABLE Waitable +{ +public: + virtual ~Waitable() {} + + /// \brief Maximum number of wait objects that this object can return + /// \return the maximum number of wait objects + virtual unsigned int GetMaxWaitObjectCount() const =0; + + /// \brief Retrieves waitable objects + /// \param container the wait container to receive the references to the objects. + /// \param callStack CallStack() object used to select waitable objects + /// \details GetWaitObjects() is usually called in one of two ways. First, it can + /// be called like something.GetWaitObjects(c, CallStack("my func after X", 0));. + /// Second, if in an outer GetWaitObjects() method that itself takes a callStack + /// parameter, it can be called like + /// innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack));. + virtual void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) =0; + + /// \brief Wait on this object + /// \return true if the wait succeeded, false otherwise + /// \details Wait() is the same as creating an empty container, calling GetWaitObjects(), and then calling + /// Wait() on the container. + bool Wait(unsigned long milliseconds, CallStack const& callStack); +}; + +/// \brief Interface for buffered transformations +/// \details BufferedTransformation is a generalization of BlockTransformation, +/// StreamTransformation and HashTransformation. +/// \details A buffered transformation is an object that takes a stream of bytes as input (this may +/// be done in stages), does some computation on them, and then places the result into an internal +/// buffer for later retrieval. Any partial result already in the output buffer is not modified +/// by further input. +/// \details If a method takes a "blocking" parameter, and you pass false for it, then the method +/// will return before all input has been processed if the input cannot be processed without waiting +/// (for network buffers to become available, for example). In this case the method will return true +/// or a non-zero integer value. When this happens you must continue to call the method with the same +/// parameters until it returns false or zero, before calling any other method on it or attached +/// BufferedTransformation. The integer return value in this case is approximately +/// the number of bytes left to be processed, and can be used to implement a progress bar. +/// \details For functions that take a "propagation" parameter, propagation != 0 means pass on +/// the signal to attached BufferedTransformation objects, with propagation decremented at each +/// step until it reaches 0. -1 means unlimited propagation. +/// \details \a All of the retrieval functions, like Get() and GetWord32(), return the actual +/// number of bytes retrieved, which is the lesser of the request number and MaxRetrievable(). +/// \details \a Most of the input functions, like Put() and PutWord32(), return the number of +/// bytes remaining to be processed. A 0 value means all bytes were processed, and a non-0 value +/// means bytes remain to be processed. +/// \nosubgrouping +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable +{ +public: + virtual ~BufferedTransformation() {} + + /// \brief Construct a BufferedTransformation + BufferedTransformation() : Algorithm(false) {} + + /// \brief Provides a reference to this object + /// \return A reference to this object + /// \details Useful for passing a temporary object to a function that takes a non-const reference + BufferedTransformation& Ref() {return *this;} + + /// \name INPUT + //@{ + + /// \brief Input a byte for processing + /// \param inByte the 8-bit byte (octet) to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). + /// 0 indicates all bytes were processed. + /// \details Put(byte) calls Put(byte*, size_t). + size_t Put(byte inByte, bool blocking=true) + {return Put(&inByte, 1, blocking);} + + /// \brief Input a byte buffer for processing + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). + /// 0 indicates all bytes were processed. + /// \details Internally, Put() calls Put2(). + size_t Put(const byte *inString, size_t length, bool blocking=true) + {return Put2(inString, length, 0, blocking);} + + /// Input a 16-bit word for processing. + /// \param value the 16-bit value to be processed + /// \param order the ByteOrder of the value to be processed. + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). + /// 0 indicates all bytes were processed. + size_t PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + /// Input a 32-bit word for processing. + /// \param value the 32-bit value to be processed. + /// \param order the ByteOrder of the value to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). + /// 0 indicates all bytes were processed. + size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + /// Input a 64-bit word for processing. + /// \param value the 64-bit value to be processed. + /// \param order the ByteOrder of the value to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). + /// 0 indicates all bytes were processed. + size_t PutWord64(word64 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + /// \brief Request space which can be written into by the caller + /// \param size the requested size of the buffer + /// \return byte pointer to the space to input data + /// \details The purpose of this method is to help avoid extra memory allocations. + /// \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made, + /// size is the requested size of the buffer. When the call returns, size is the size of + /// the array returned to the caller. + /// \details The base class implementation sets size to 0 and returns NULL. + /// \note Some objects, like ArraySink, cannot create a space because its fixed. In the case of + /// an ArraySink, the pointer to the array is returned and the size is remaining size. + virtual byte * CreatePutSpace(size_t &size) + {size=0; return NULLPTR;} + + /// \brief Determines whether input can be modified by the callee + /// \return true if input can be modified, false otherwise + /// \details The base class implementation returns false. + virtual bool CanModifyInput() const + {return false;} + + /// \brief Input multiple bytes that may be modified by callee. + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). 0 indicates all + /// bytes were processed. + size_t PutModifiable(byte *inString, size_t length, bool blocking=true) + {return PutModifiable2(inString, length, 0, blocking);} + + /// \brief Signals the end of messages to the object + /// \param propagation the number of attached transformations the MessageEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + bool MessageEnd(int propagation=-1, bool blocking=true) + {return !!Put2(NULLPTR, 0, propagation < 0 ? -1 : propagation+1, blocking);} + + /// \brief Input multiple bytes for processing and signal the end of a message + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param propagation the number of attached transformations the MessageEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). 0 indicates all + /// bytes were processed. + /// \details Internally, PutMessageEnd() calls Put2() with a modified propagation to + /// ensure all attached transformations finish processing the message. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true) + {return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);} + + /// \brief Input multiple bytes for processing + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). 0 indicates all + /// bytes were processed. + /// \details Derived classes must implement Put2(). + virtual size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) =0; + + /// \brief Input multiple bytes that may be modified by callee. + /// \param inString the byte buffer to process. + /// \param length the size of the string, in bytes. + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed). 0 indicates all + /// bytes were processed. + /// \details Internally, PutModifiable2() calls Put2(). + virtual size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) + {return Put2(inString, length, messageEnd, blocking);} + + /// \brief Exception thrown by objects that have \a not implemented nonblocking input processing + /// \details BlockingInputOnly inherits from NotImplemented + struct BlockingInputOnly : public NotImplemented + {BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}}; + //@} + + /// \name WAITING + //@{ + /// \brief Retrieves the maximum number of waitable objects + unsigned int GetMaxWaitObjectCount() const; + + /// \brief Retrieves waitable objects + /// \param container the wait container to receive the references to the objects + /// \param callStack CallStack() object used to select waitable objects + /// \details GetWaitObjects is usually called in one of two ways. First, it can + /// be called like something.GetWaitObjects(c, CallStack("my func after X", 0));. + /// Second, if in an outer GetWaitObjects() method that itself takes a callStack + /// parameter, it can be called like + /// innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack));. + void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); + //@} // WAITING + + /// \name SIGNALS + //@{ + + /// \brief Initialize or reinitialize this object, without signal propagation + /// \param parameters a set of NameValuePairs to initialize this object + /// \throw NotImplemented + /// \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable + /// number of arbitrarily typed arguments. The function avoids the need for multiple constructors providing + /// all possible combintations of configurable parameters. + /// \details IsolatedInitialize() does not call Initialize() on attached transformations. If initialization + /// should be propagated, then use the Initialize() function. + /// \details If a derived class does not override IsolatedInitialize(), then the base class throws + /// NotImplemented. + virtual void IsolatedInitialize(const NameValuePairs ¶meters) { + CRYPTOPP_UNUSED(parameters); + throw NotImplemented("BufferedTransformation: this object can't be reinitialized"); + } + + /// \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 + /// \note hardFlush must be used with care + virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0; + + /// \brief Marks the end of a series of messages, without signal propagation + /// \param blocking specifies whether the object should block when completing the processing on + /// the current series of messages + /// \return true if the message was successful, false otherwise + virtual bool IsolatedMessageSeriesEnd(bool blocking) + {CRYPTOPP_UNUSED(blocking); return false;} + + /// \brief Initialize or reinitialize this object, with signal propagation + /// \param parameters a set of NameValuePairs to initialize or reinitialize this object + /// \param propagation the number of attached transformations the Initialize() signal should be passed + /// \details Initialize() is used to initialize or reinitialize an object using a variable number of + /// arbitrarily typed arguments. The function avoids the need for multiple constructors providing + /// all possible combintations of configurable parameters. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); + + /// \brief Flush buffered input and/or output, with signal propagation + /// \param hardFlush is used to indicate whether all data should be flushed + /// \param propagation the number of attached transformations the Flush() + /// signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true if the flush was successful, false otherwise + /// \details propagation count includes this object. Setting propagation to + /// 1 means this object only. Setting propagation to -1 + /// 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. + /// \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. + virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); + + /// \brief Marks the end of a series of messages, with signal propagation + /// \param propagation the number of attached transformations the MessageSeriesEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true if the message 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. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + /// \note There should be a MessageEnd() immediately before MessageSeriesEnd(). + virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true); + + /// \brief Set propagation of automatically generated and transferred signals + /// \param propagation then new value + /// \details Setting propagation to 0 means do not automatically generate signals. Setting + /// propagation to -1 means unlimited propagation. + virtual void SetAutoSignalPropagation(int propagation) + {CRYPTOPP_UNUSED(propagation);} + + /// \brief Retrieve automatic signal propagation value + /// \return the number of attached transformations the signal is propagated to. 0 indicates + /// the signal is only witnessed by this object + virtual int GetAutoSignalPropagation() const {return 0;} +public: + + /// \name RETRIEVAL OF ONE MESSAGE + //@{ + + /// \brief Provides the number of bytes ready for retrieval + /// \return the number of bytes ready for retrieval + /// \details The number of bytes available are dependent on the source. If an exact value is + /// available, then the exact value is returned. The exact value can include 0 if the source + /// is exhausted. + /// \details Some stream-based sources do not allow seeking() on the underlying stream, such + /// as some FileSource(). If the stream does not allow seeking() then MaxRetrievable() + /// returns LWORD_MAX to indicate there are still bytes to be retrieved. + virtual lword MaxRetrievable() const; + + /// \brief Determines whether bytes are ready for retrieval + /// \return true if bytes are available for retrieval, false otherwise + virtual bool AnyRetrievable() const; + + /// \brief Retrieve a 8-bit byte + /// \param outByte the 8-bit value to be retrieved + /// \return the number of bytes consumed during the call. + /// \details Use the return value of Get to detect short reads. + virtual size_t Get(byte &outByte); + + /// \brief Retrieve a block of bytes + /// \param outString a block of bytes + /// \param getMax the number of bytes to Get + /// \return the number of bytes consumed during the call. + /// \details Use the return value of Get to detect short reads. + virtual size_t Get(byte *outString, size_t getMax); + + /// \brief Peek a 8-bit byte + /// \param outByte the 8-bit value to be retrieved + /// \return the number of bytes read during the call. + /// \details Peek does not remove bytes from the object. Use the return value of + /// Get() to detect short reads. + virtual size_t Peek(byte &outByte) const; + + /// \brief Peek a block of bytes + /// \param outString a block of bytes + /// \param peekMax the number of bytes to Peek + /// \return the number of bytes read during the call. + /// \details Peek does not remove bytes from the object. Use the return value of + /// Peek() to detect short reads. + virtual size_t Peek(byte *outString, size_t peekMax) const; + + /// \brief Retrieve a 16-bit word + /// \param value the 16-bit value to be retrieved + /// \param order the ByteOrder of the value to be processed. + /// \return the number of bytes consumed during the call. + /// \details Use the return value of GetWord16() to detect short reads. + size_t GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER); + + /// \brief Retrieve a 32-bit word + /// \param value the 32-bit value to be retrieved + /// \param order the ByteOrder of the value to be processed. + /// \return the number of bytes consumed during the call. + /// \details Use the return value of GetWord32() to detect short reads. + size_t GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER); + + /// \brief Retrieve a 64-bit word + /// \param value the 64-bit value to be retrieved + /// \param order the ByteOrder of the value to be processed. + /// \return the number of bytes consumed during the call. + /// \details Use the return value of GetWord64() to detect short reads. + /// \since Crypto++ 8.3 + size_t GetWord64(word64 &value, ByteOrder order=BIG_ENDIAN_ORDER); + + /// \brief Peek a 16-bit word + /// \param value the 16-bit value to be retrieved + /// \param order the ByteOrder of the value to be processed. + /// \return the number of bytes consumed during the call. + /// \details Peek does not consume bytes in the stream. Use the return value + /// of PeekWord16() to detect short reads. + size_t PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; + + /// \brief Peek a 32-bit word + /// \param value the 32-bit value to be retrieved + /// \param order the ByteOrder of the value to be processed. + /// \return the number of bytes consumed during the call. + /// \details Peek does not consume bytes in the stream. Use the return value + /// of PeekWord32() to detect short reads. + size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; + + /// \brief Peek a 64-bit word + /// \param value the 64-bit value to be retrieved + /// \param order the ByteOrder of the value to be processed. + /// \return the number of bytes consumed during the call. + /// \details Peek does not consume bytes in the stream. Use the return value + /// of PeekWord64() to detect short reads. + /// \since Crypto++ 8.3 + size_t PeekWord64(word64 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; + + /// move transferMax bytes of the buffered output to target as input + + /// \brief Transfer bytes from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param transferMax the number of bytes to transfer + /// \param channel the channel on which the transfer should occur + /// \return the number of bytes transferred during the call. + /// \details TransferTo removes bytes from this object and moves them to the destination. + /// \details The function always returns transferMax. If an accurate count is needed, then use TransferTo2(). + lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) + {TransferTo2(target, transferMax, channel); return transferMax;} + + /// \brief Discard skipMax bytes from the output buffer + /// \param skipMax the number of bytes to discard + /// \details Skip() discards bytes from the output buffer, which is the AttachedTransformation(), if present. + /// The function always returns the parameter skipMax. + /// \details If you want to skip bytes from a Source, then perform the following. + ///
  StringSource ss(str, false, new Redirector(TheBitBucket()));
+		///   ss.Pump(10);    // Skip 10 bytes from Source
+		///   ss.Detach(new FilterChain(...));
+		///   ss.PumpAll();
+		/// 
+ virtual lword Skip(lword skipMax=LWORD_MAX); + + /// \brief Copy bytes from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param copyMax the number of bytes to copy + /// \param channel the channel on which the transfer should occur + /// \return the number of bytes copied during the call. + /// \details CopyTo copies bytes from this object to the destination. The bytes are not removed from this object. + /// \details The function always returns copyMax. If an accurate count is needed, then use CopyRangeTo2(). + lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const + {return CopyRangeTo(target, 0, copyMax, channel);} + + /// \brief Copy bytes from this object using an index to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param position the 0-based index of the byte stream to begin the copying + /// \param copyMax the number of bytes to copy + /// \param channel the channel on which the transfer should occur + /// \return the number of bytes copied during the call. + /// \details CopyTo copies bytes from this object to the destination. The bytes remain in this + /// object. Copying begins at the index position in the current stream, and not from an absolute + /// position in the stream. + /// \details The function returns the new position in the stream after transferring the bytes starting at the index. + lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const + {lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;} + //@} + + /// \name RETRIEVAL OF MULTIPLE MESSAGES + //@{ + + /// \brief Provides the number of bytes ready for retrieval + /// \return the number of bytes ready for retrieval + virtual lword TotalBytesRetrievable() const; + + /// \brief Provides the number of meesages processed by this object + /// \return the number of meesages processed by this object + /// \details NumberOfMessages returns number of times MessageEnd() has been + /// received minus messages retrieved or skipped + virtual unsigned int NumberOfMessages() const; + + /// \brief Determines if any messages are available for retrieval + /// \return true if NumberOfMessages() > 0, false otherwise + /// \details AnyMessages returns true if NumberOfMessages() > 0 + virtual bool AnyMessages() const; + + /// \brief Start retrieving the next message + /// \return true if a message is ready for retrieval + /// \details GetNextMessage() returns true if a message is ready for retrieval; false + /// if no more messages exist or this message is not completely retrieved. + virtual bool GetNextMessage(); + + /// \brief Skip a number of meessages + /// \param count number of messages to skip + /// \return 0 if the requested number of messages was skipped, non-0 otherwise + /// \details SkipMessages() skips count number of messages. If there is an AttachedTransformation() + /// then SkipMessages() is called on the attached transformation. If there is no attached + /// transformation, then count number of messages are sent to TheBitBucket() using TransferMessagesTo(). + virtual unsigned int SkipMessages(unsigned int count=UINT_MAX); + + /// \brief Transfer messages from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param count the number of messages to transfer + /// \param channel the channel on which the transfer should occur + /// \return the number of bytes that remain in the current transfer block (i.e., bytes not transferred) + /// \details TransferMessagesTo2() removes messages from this object and moves them to the destination. + /// If all bytes are not transferred for a message, then processing stops and the number of remaining + /// bytes is returned. TransferMessagesTo() does not proceed to the next message. + /// \details A return value of 0 indicates all messages were successfully transferred. + unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) + {TransferMessagesTo2(target, count, channel); return count;} + + /// \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 copy should occur + /// \return the number of bytes that remain in the current transfer block (i.e., bytes not transferred) + /// \details CopyMessagesTo copies messages from this object to the destination. + /// If all bytes are not transferred for a message, then processing stops and the number of remaining + /// bytes is returned. CopyMessagesTo() does not proceed to the next message. + /// \details A return value of 0 indicates all messages were successfully copied. + unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; + + /// \brief Skip all messages in the series + virtual void SkipAll(); + + /// \brief Transfer all bytes from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param channel the channel on which the transfer should occur + /// \details TransferMessagesTo2() removes messages from this object and moves them to the destination. + /// Internally TransferAllTo() calls TransferAllTo2(). + void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) + {TransferAllTo2(target, channel);} + + /// \brief Copy messages from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param channel the channel on which the transfer should occur + /// \details CopyAllTo copies messages from this object and copies them to the destination. + void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const; + + /// \brief Retrieve the next message in a series + /// \return true if a message was retrieved, false otherwise + /// \details Internally, the base class implementation returns false. + virtual bool GetNextMessageSeries() {return false;} + /// \brief Provides the number of messages in a series + /// \return the number of messages in this series + virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();} + /// \brief Provides the number of messages in a series + /// \return the number of messages in this series + virtual unsigned int NumberOfMessageSeries() const {return 0;} + //@} + + /// \name NON-BLOCKING TRANSFER OF OUTPUT + //@{ + + // upon return, byteCount contains number of bytes that have finished being transferred, + // and returns the number of bytes left in the current transfer block + + /// \brief Transfer bytes from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param byteCount 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 from this object 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 byteCount is an \a IN and \a OUT parameter. When the call is made, + /// byteCount is the requested size of the transfer. When the call returns, byteCount is + /// the number of bytes that were transferred. + virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0; + + // upon return, begin contains the start position of data yet to be finished copying, + // and returns the number of bytes left in the current transfer block + + /// \brief Copy bytes from this object 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 from this object 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(). + virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0; + + // upon return, messageCount contains number of messages that have finished being transferred, + // and returns the number of bytes left in the current transfer block + + /// \brief Transfer messages from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param messageCount the number of messages 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 current transfer block (i.e., bytes not transferred) + /// \details TransferMessagesTo2() removes messages from this object and moves them to the destination. + /// \details messageCount is an \a IN and \a OUT parameter. When the call is made, messageCount is the + /// the number of messages requested to be transferred. When the call returns, messageCount is the + /// number of messages actually transferred. + size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + + // returns the number of bytes left in the current transfer block + + /// \brief Transfer all bytes from this object to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \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 current transfer block (i.e., bytes not transferred) + /// \details TransferMessagesTo2() removes messages from this object and moves them to the destination. + size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + //@} + + /// \name CHANNELS + //@{ + /// \brief Exception thrown when a filter does not support named channels + struct NoChannelSupport : public NotImplemented + {NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}}; + /// \brief Exception thrown when a filter does not recognize a named channel + struct InvalidChannelName : public InvalidArgument + {InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}}; + + /// \brief Input a byte for processing on a channel + /// \param channel the channel to process the data. + /// \param inByte the 8-bit byte (octet) to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true) + {return ChannelPut(channel, &inByte, 1, blocking);} + + /// \brief Input a byte buffer for processing on a channel + /// \param channel the channel to process the data + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param blocking specifies whether the object should block when processing input + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + size_t ChannelPut(const std::string &channel, const byte *inString, size_t length, bool blocking=true) + {return ChannelPut2(channel, inString, length, 0, blocking);} + + /// \brief Input multiple bytes that may be modified by callee on a channel + /// \param channel the channel to process the data. + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param blocking specifies whether the object should block when processing input + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + size_t ChannelPutModifiable(const std::string &channel, byte *inString, size_t length, bool blocking=true) + {return ChannelPutModifiable2(channel, inString, length, 0, blocking);} + + /// \brief Input a 16-bit word for processing on a channel. + /// \param channel the channel to process the data. + /// \param value the 16-bit value to be processed. + /// \param order the ByteOrder of the value to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + size_t ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + /// \brief Input a 32-bit word for processing on a channel. + /// \param channel the channel to process the data. + /// \param value the 32-bit value to be processed. + /// \param order the ByteOrder of the value to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + size_t ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + /// \brief Input a 64-bit word for processing on a channel. + /// \param channel the channel to process the data. + /// \param value the 64-bit value to be processed. + /// \param order the ByteOrder of the value to be processed. + /// \param blocking specifies whether the object should block when processing input. + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + size_t ChannelPutWord64(const std::string &channel, word64 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + /// \brief Signal the end of a message + /// \param channel the channel to process the data. + /// \param propagation the number of attached transformations the ChannelMessageEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return 0 indicates all bytes were processed during the call. Non-0 indicates the + /// number of bytes that were not processed. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true) + {return !!ChannelPut2(channel, NULLPTR, 0, propagation < 0 ? -1 : propagation+1, blocking);} + + /// \brief Input multiple bytes for processing and signal the end of a message + /// \param channel the channel to process the data. + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param propagation the number of attached transformations the ChannelPutMessageEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + size_t ChannelPutMessageEnd(const std::string &channel, const byte *inString, size_t length, int propagation=-1, bool blocking=true) + {return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);} + + /// \brief Request space which can be written into by the caller + /// \param channel the channel to process the data + /// \param size the requested size of the buffer + /// \return a pointer to a memory block with length size + /// \details The purpose of this method is to help avoid extra memory allocations. + /// \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made, + /// size is the requested size of the buffer. When the call returns, size is the size of + /// the array returned to the caller. + /// \details The base class implementation sets size to 0 and returns NULL. + /// \note Some objects, like ArraySink(), cannot create a space because its fixed. In the case of + /// an ArraySink(), the pointer to the array is returned and the size is remaining size. + virtual byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); + + /// \brief Input multiple bytes for processing on a channel. + /// \param channel the channel to process the data. + /// \param inString the byte buffer to process. + /// \param length the size of the string, in bytes. + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + virtual size_t ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking); + + /// \brief Input multiple bytes that may be modified by callee on a channel + /// \param channel the channel to process the data + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + virtual size_t ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking); + + /// \brief Flush buffered input and/or output on a channel + /// \param channel the channel to flush the data + /// \param hardFlush is used to indicate whether all data should be flushed + /// \param propagation the number of attached transformations the ChannelFlush() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true of the Flush was successful + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true); + + /// \brief Marks the end of a series of messages on a channel + /// \param channel the channel to signal the end of a series of messages + /// \param propagation the number of attached transformations the ChannelMessageSeriesEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true if the message 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. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + /// \note There should be a MessageEnd() immediately before MessageSeriesEnd(). + virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); + + /// \brief Sets the default retrieval channel + /// \param channel the channel to signal the end of a series of messages + /// \note this function may not be implemented in all objects that should support it. + virtual void SetRetrievalChannel(const std::string &channel); + //@} + + /// \name ATTACHMENT + /// \details Some BufferedTransformation objects (e.g. Filter objects) allow other BufferedTransformation objects to be + /// attached. When this is done, the first object instead of buffering its output, sends that output to the attached + /// object as input. The entire attachment chain is deleted when the anchor object is destructed. + + //@{ + /// \brief Determines whether the object allows attachment + /// \return true if the object allows an attachment, false otherwise + /// \details Sources and Filters will returns true, while Sinks and other objects will return false. + virtual bool Attachable() {return false;} + + /// \brief Returns the object immediately attached to this object + /// \return the attached transformation + /// \details AttachedTransformation() returns NULL if there is no attachment. The non-const + /// version of AttachedTransformation() always returns NULL. + virtual BufferedTransformation *AttachedTransformation() {CRYPTOPP_ASSERT(!Attachable()); return NULLPTR;} + + /// \brief Returns the object immediately attached to this object + /// \return the attached transformation + /// \details AttachedTransformation() returns NULL if there is no attachment. The non-const + /// version of AttachedTransformation() always returns NULL. + virtual const BufferedTransformation *AttachedTransformation() const + {return const_cast(this)->AttachedTransformation();} + + /// \brief Delete the current attachment chain and attach a new one + /// \param newAttachment the new BufferedTransformation to attach + /// \throw NotImplemented + /// \details Detach() deletes the current attachment chain and replace it with an optional newAttachment + /// \details If a derived class does not override Detach(), then the base class throws + /// NotImplemented. + virtual void Detach(BufferedTransformation *newAttachment = NULLPTR) { + CRYPTOPP_UNUSED(newAttachment); CRYPTOPP_ASSERT(!Attachable()); + throw NotImplemented("BufferedTransformation: this object is not attachable"); + } + + /// \brief Add newAttachment to the end of attachment chain + /// \param newAttachment the attachment to add to the end of the chain + virtual void Attach(BufferedTransformation *newAttachment); + //@} + +protected: + /// \brief Decrements the propagation count while clamping at 0 + /// \return the decremented propagation or 0 + static int DecrementPropagation(int propagation) + {return propagation != 0 ? propagation - 1 : 0;} + +private: + // for ChannelPutWord16, ChannelPutWord32 and ChannelPutWord64, + // to ensure the buffer isn't deallocated before non-blocking + // operation completes + byte m_buf[8]; +}; + +/// \brief An input discarding BufferedTransformation +/// \return a reference to a BufferedTransformation object that discards all input +CRYPTOPP_DLL BufferedTransformation & TheBitBucket(); + +/// \brief Interface for crypto material +/// \details CryptoMaterial() is an interface for crypto material, such as +/// public keys, private keys and crypto parameters. Derived classes generally +/// do not offer public methods such as GenerateRandom() and +/// GenerateRandomWithKeySize(). +/// \sa GeneratableCryptoMaterial() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs +{ +public: + /// Exception thrown when invalid crypto material is detected + class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat + { + public: + explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {} + }; + + virtual ~CryptoMaterial() {} + + /// \brief Assign values to this object + /// \details This function can be used to create a public key from a private key. + virtual void AssignFrom(const NameValuePairs &source) =0; + + /// \brief Check this object for errors + /// \param rng a RandomNumberGenerator for objects which use randomized testing + /// \param level the level of thoroughness + /// \return true if the tests succeed, false otherwise + /// \details There are four levels of thoroughness: + ///
    + ///
  • 0 - using this object won't cause a crash or exception + ///
  • 1 - this object will probably function, and encrypt, sign, other operations correctly + ///
  • 2 - ensure this object will function correctly, and perform reasonable security checks + ///
  • 3 - perform reasonable security checks, and do checks that may take a long time + ///
+ /// \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. + /// \sa ThrowIfInvalid() + virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0; + + /// \brief Check this object for errors + /// \param rng a RandomNumberGenerator for objects which use randomized testing + /// \param level the level of thoroughness + /// \throw InvalidMaterial + /// \details Internally, ThrowIfInvalid() calls Validate() and throws InvalidMaterial() if validation fails. + /// \sa Validate() + virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const + {if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");} + + /// \brief Saves a key to a BufferedTransformation + /// \param bt the destination BufferedTransformation + /// \throw NotImplemented + /// \details Save() writes the material to a BufferedTransformation. + /// \details If the material is a key, then the key is written with ASN.1 DER encoding. The key + /// includes an object identifier with an algorithm id, like a subjectPublicKeyInfo. + /// \details A "raw" key without the "key info" can be saved using a key's DEREncode() method. + /// \details If a derived class does not override Save(), then the base class throws + /// NotImplemented(). + virtual void Save(BufferedTransformation &bt) const + {CRYPTOPP_UNUSED(bt); throw NotImplemented("CryptoMaterial: this object does not support saving");} + + /// \brief Loads a key from a BufferedTransformation + /// \param bt the source BufferedTransformation + /// \throw KeyingErr + /// \details Load() attempts to read material from a BufferedTransformation. If the + /// material is a key that was generated outside the library, then the following + /// usually applies: + ///
    + ///
  • the key should be ASN.1 BER encoded + ///
  • the key should be a "key info" + ///
+ /// \details "key info" means the key should have an object identifier with an algorithm id, + /// like a subjectPublicKeyInfo. + /// \details To read a "raw" key without the "key info", then call the key's BERDecode() method. + /// \note Load() generally does not check that the key is valid. Call Validate(), if needed. + virtual void Load(BufferedTransformation &bt) + {CRYPTOPP_UNUSED(bt); throw NotImplemented("CryptoMaterial: this object does not support loading");} + + /// \brief Determines whether the object supports precomputation + /// \return true if the object supports precomputation, false otherwise + /// \sa Precompute() + virtual bool SupportsPrecomputation() const {return false;} + + /// \brief Perform precomputation + /// \param precomputationStorage the suggested number of objects for the precompute table + /// \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. + /// \details If a derived class does not override Precompute(), then the base class throws + /// NotImplemented. + /// \sa SupportsPrecomputation(), LoadPrecomputation(), SavePrecomputation() + virtual void Precompute(unsigned int precomputationStorage) { + CRYPTOPP_UNUSED(precomputationStorage); CRYPTOPP_ASSERT(!SupportsPrecomputation()); + throw NotImplemented("CryptoMaterial: this object does not support precomputation"); + } + + /// \brief Retrieve previously saved precomputation + /// \param storedPrecomputation BufferedTransformation with the saved precomputation + /// \throw NotImplemented + /// \sa SupportsPrecomputation(), Precompute() + virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + {CRYPTOPP_UNUSED(storedPrecomputation); CRYPTOPP_ASSERT(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} + + /// \brief Save precomputation for later use + /// \param storedPrecomputation BufferedTransformation to write the precomputation + /// \throw NotImplemented + /// \sa SupportsPrecomputation(), Precompute() + virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + {CRYPTOPP_UNUSED(storedPrecomputation); CRYPTOPP_ASSERT(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} + + /// \brief Perform a quick sanity check + /// \details DoQuickSanityCheck() is for internal library use, and it should not be called by library users. + void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);} + +#if defined(__SUNPRO_CC) + // Sun Studio 11/CC 5.8 workaround: it generates incorrect code + // when casting to an empty virtual base class. JW, 2018: It is + // still a problem in Sun Studio 12.6/CC 5.15 on i386. Just enable + // it everywhere in case it affects SPARC (which we don't test). + char m_sunCCworkaround; +#endif +}; + +/// \brief Interface for crypto material +/// \details GeneratableCryptoMaterial() is an interface for crypto material, +/// such as private keys and crypto parameters. Derived classes offer public +/// methods such as GenerateRandom() and GenerateRandomWithKeySize(). +/// \sa CryptoMaterial() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial +{ +public: + virtual ~GeneratableCryptoMaterial() {} + + /// \brief Generate a random key or crypto parameters + /// \param rng a RandomNumberGenerator to produce keying material + /// \param params additional initialization parameters + /// \throw KeyingErr if a key can't be generated or algorithm parameters are invalid + /// \details If a derived class does not override GenerateRandom(), then the base class throws + /// NotImplemented. + virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) { + CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(params); + throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation"); + } + + /// \brief Generate a random key or crypto parameters + /// \param rng a RandomNumberGenerator to produce keying material + /// \param keySize the size of the key, in bits + /// \throw KeyingErr if a key can't be generated or algorithm parameters are invalid + /// \details GenerateRandomWithKeySize calls GenerateRandom() with a NameValuePairs + /// object with only "KeySize" + void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize); +}; + +/// \brief Interface for public keys +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial +{ +}; + +/// \brief Interface for private keys +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial +{ +}; + +/// \brief Interface for crypto parameters +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoParameters : public GeneratableCryptoMaterial +{ +}; + +/// \brief Interface for certificates +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Certificate : virtual public CryptoMaterial +{ +}; + +/// \brief Interface for asymmetric algorithms +/// \details BERDecode() and DEREncode() were removed under Issue 569 +/// and Commit 9b174e84de7a. Programs should use AccessMaterial().Load(bt) +/// or GetMaterial().Save(bt) instead. +/// \sa Issue 569 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm +{ +public: + virtual ~AsymmetricAlgorithm() {} + + /// \brief Retrieves a reference to CryptoMaterial + /// \return a reference to the crypto material + virtual CryptoMaterial & AccessMaterial() =0; + + /// \brief Retrieves a reference to CryptoMaterial + /// \return a const reference to the crypto material + virtual const CryptoMaterial & GetMaterial() const =0; + +#if 0 + /// \brief Loads this object from a BufferedTransformation + /// \param bt a BufferedTransformation object + /// \details Use of BERDecode() changed to Load() at Issue 569. + /// \deprecated for backwards compatibility, calls AccessMaterial().Load(bt) + void BERDecode(BufferedTransformation &bt) + {AccessMaterial().Load(bt);} + + /// \brief Saves this object to a BufferedTransformation + /// \param bt a BufferedTransformation object + /// \details Use of DEREncode() changed to Save() at Issue 569. + /// \deprecated for backwards compatibility, calls GetMaterial().Save(bt) + void DEREncode(BufferedTransformation &bt) const + {GetMaterial().Save(bt);} +#endif +}; + +/// \brief Interface for asymmetric algorithms using public keys +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm +{ +public: + virtual ~PublicKeyAlgorithm() {} + + // VC60 workaround: no co-variant return type + + /// \brief Retrieves a reference to a Public Key + /// \return a reference to the public key + CryptoMaterial & AccessMaterial() + {return AccessPublicKey();} + /// \brief Retrieves a reference to a Public Key + /// \return a const reference the public key + const CryptoMaterial & GetMaterial() const + {return GetPublicKey();} + + /// \brief Retrieves a reference to a Public Key + /// \return a reference to the public key + virtual PublicKey & AccessPublicKey() =0; + /// \brief Retrieves a reference to a Public Key + /// \return a const reference the public key + virtual const PublicKey & GetPublicKey() const + {return const_cast(this)->AccessPublicKey();} +}; + +/// \brief Interface for asymmetric algorithms using private keys +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm +{ +public: + virtual ~PrivateKeyAlgorithm() {} + + /// \brief Retrieves a reference to a Private Key + /// \return a reference the private key + CryptoMaterial & AccessMaterial() {return AccessPrivateKey();} + /// \brief Retrieves a reference to a Private Key + /// \return a const reference the private key + const CryptoMaterial & GetMaterial() const {return GetPrivateKey();} + + /// \brief Retrieves a reference to a Private Key + /// \return a reference the private key + virtual PrivateKey & AccessPrivateKey() =0; + /// \brief Retrieves a reference to a Private Key + /// \return a const reference the private key + virtual const PrivateKey & GetPrivateKey() const {return const_cast(this)->AccessPrivateKey();} +}; + +/// \brief Interface for key agreement algorithms +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyAgreementAlgorithm : public AsymmetricAlgorithm +{ +public: + virtual ~KeyAgreementAlgorithm() {} + + /// \brief Retrieves a reference to Crypto Parameters + /// \return a reference the crypto parameters + CryptoMaterial & AccessMaterial() {return AccessCryptoParameters();} + /// \brief Retrieves a reference to Crypto Parameters + /// \return a const reference the crypto parameters + const CryptoMaterial & GetMaterial() const {return GetCryptoParameters();} + + /// \brief Retrieves a reference to Crypto Parameters + /// \return a reference the crypto parameters + virtual CryptoParameters & AccessCryptoParameters() =0; + /// \brief Retrieves a reference to Crypto Parameters + /// \return a const reference the crypto parameters + virtual const CryptoParameters & GetCryptoParameters() const {return const_cast(this)->AccessCryptoParameters();} +}; + +/// \brief Interface for public-key encryptors and decryptors +/// \details This class provides an interface common to encryptors and decryptors +/// for querying their plaintext and ciphertext lengths. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem +{ +public: + virtual ~PK_CryptoSystem() {} + + /// \brief Provides the maximum length of plaintext for a given ciphertext length + /// \return the maximum size of the plaintext, in bytes + /// \details This function returns 0 if ciphertextLength is not valid (too long or too short). + virtual size_t MaxPlaintextLength(size_t ciphertextLength) const =0; + + /// \brief Calculate the length of ciphertext given length of plaintext + /// \return the maximum size of the ciphertext, in bytes + /// \details This function returns 0 if plaintextLength is not valid (too long). + virtual size_t CiphertextLength(size_t plaintextLength) const =0; + + /// \brief Determines whether this object supports the use of a named parameter + /// \param name the name of the parameter + /// \return true if the parameter name is supported, false otherwise + /// \details Some possible parameter names: EncodingParameters(), KeyDerivationParameters() + /// and others Parameters listed in argnames.h + virtual bool ParameterSupported(const char *name) const =0; + + /// \brief Provides the fixed ciphertext length, if one exists + /// \return the fixed ciphertext length if one exists, otherwise 0 + /// \details "Fixed" here means length of ciphertext does not depend on length of plaintext. + /// In this case, it usually does depend on the key length. + virtual size_t FixedCiphertextLength() const {return 0;} + + /// \brief Provides the maximum plaintext length given a fixed ciphertext length + /// \return maximum plaintext length given the fixed ciphertext length, if one exists, + /// otherwise return 0. + /// \details FixedMaxPlaintextLength(0 returns the maximum plaintext length given the fixed ciphertext + /// length, if one exists, otherwise return 0. + virtual size_t FixedMaxPlaintextLength() const {return 0;} +}; + +/// \brief Interface for public-key encryptors +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : public PK_CryptoSystem, public PublicKeyAlgorithm +{ +public: + /// \brief Exception thrown when trying to encrypt plaintext of invalid length + class CRYPTOPP_DLL InvalidPlaintextLength : public Exception + { + public: + InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {} + }; + + /// \brief Encrypt a byte string + /// \param rng a RandomNumberGenerator derived class + /// \param plaintext the plaintext byte buffer + /// \param plaintextLength the size of the plaintext byte buffer + /// \param ciphertext a byte buffer to hold the encrypted string + /// \param parameters a set of NameValuePairs to initialize this object + /// \pre CiphertextLength(plaintextLength) != 0 ensures the plaintext isn't too large + /// \pre COUNTOF(ciphertext) == CiphertextLength(plaintextLength) ensures the output + /// byte buffer is large enough. + /// \sa PK_Decryptor + virtual void Encrypt(RandomNumberGenerator &rng, + const byte *plaintext, size_t plaintextLength, + byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; + + /// \brief Create a new encryption filter + /// \param rng a RandomNumberGenerator derived class + /// \param attachment an attached transformation + /// \param parameters a set of NameValuePairs to initialize this object + /// \details \p attachment can be \p NULL. The caller is responsible for deleting the returned pointer. + /// Encoding parameters should be passed in the "EP" channel. + virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng, + BufferedTransformation *attachment=NULLPTR, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +/// \brief Interface for public-key decryptors +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Decryptor : public PK_CryptoSystem, public PrivateKeyAlgorithm +{ +public: + virtual ~PK_Decryptor() {} + + /// \brief Decrypt a byte string + /// \param rng a RandomNumberGenerator derived class + /// \param ciphertext the encrypted byte buffer + /// \param ciphertextLength the size of the encrypted byte buffer + /// \param plaintext a byte buffer to hold the decrypted string + /// \param parameters a set of NameValuePairs to initialize this object + /// \return the result of the decryption operation + /// \details If DecodingResult::isValidCoding is true, then DecodingResult::messageLength + /// is valid and holds the actual length of the plaintext recovered. The result is undefined + /// if decryption failed. If DecodingResult::isValidCoding is false, then DecodingResult::messageLength + /// is undefined. + /// \pre COUNTOF(plaintext) == MaxPlaintextLength(ciphertextLength) ensures the output + /// byte buffer is large enough + /// \sa PK_Encryptor + virtual DecodingResult Decrypt(RandomNumberGenerator &rng, + const byte *ciphertext, size_t ciphertextLength, + byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; + + /// \brief Create a new decryption filter + /// \param rng a RandomNumberGenerator derived class + /// \param attachment an attached transformation + /// \param parameters a set of NameValuePairs to initialize this object + /// \return the newly created decryption filter + /// \note the caller is responsible for deleting the returned pointer + virtual BufferedTransformation * CreateDecryptionFilter(RandomNumberGenerator &rng, + BufferedTransformation *attachment=NULLPTR, const NameValuePairs ¶meters = g_nullNameValuePairs) const; + + /// \brief Decrypt a fixed size ciphertext + /// \param rng a RandomNumberGenerator derived class + /// \param ciphertext the encrypted byte buffer + /// \param plaintext a byte buffer to hold the decrypted string + /// \param parameters a set of NameValuePairs to initialize this object + /// \return the result of the decryption operation + /// \details If DecodingResult::isValidCoding is true, then DecodingResult::messageLength + /// is valid and holds the actual length of the plaintext recovered. The result is undefined + /// if decryption failed. If DecodingResult::isValidCoding is false, then DecodingResult::messageLength + /// is undefined. + /// \pre COUNTOF(plaintext) == MaxPlaintextLength(ciphertextLength) ensures the output + /// byte buffer is large enough + /// \sa PK_Encryptor + DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + {return Decrypt(rng, ciphertext, FixedCiphertextLength(), plaintext, parameters);} +}; + +/// \brief Interface for public-key signers and verifiers +/// \details This class provides an interface common to signers and verifiers for querying scheme properties +/// \sa DL_SignatureSchemeBase, TF_SignatureSchemeBase, DL_SignerBase, TF_SignerBase +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme +{ +public: + /// \brief Exception throw when the private or public key has a length that can't be used + /// \details InvalidKeyLength() may be thrown by any function in this class if the private + /// or public key has a length that can't be used + class CRYPTOPP_DLL InvalidKeyLength : public Exception + { + public: + InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {} + }; + + /// \brief Exception throw when the private or public key is too short to sign or verify + /// \details KeyTooShort() may be thrown by any function in this class if the private or public + /// key is too short to sign or verify anything + class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength + { + public: + KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {} + }; + + virtual ~PK_SignatureScheme() {} + + /// \brief Provides the signature length if it only depends on the key + /// \return the signature length if it only depends on the key, in bytes + /// \details SignatureLength() returns the signature length if it only depends on the key, otherwise 0. + virtual size_t SignatureLength() const =0; + + /// \brief Provides the maximum signature length produced given the length of the recoverable message part + /// \param recoverablePartLength the length of the recoverable message part, in bytes + /// \return the maximum signature length produced for a given length of recoverable message part, in bytes + /// \details MaxSignatureLength() returns the maximum signature length produced given the length of the + /// recoverable message part. + virtual size_t MaxSignatureLength(size_t recoverablePartLength = 0) const + {CRYPTOPP_UNUSED(recoverablePartLength); return SignatureLength();} + + /// \brief Provides the length of longest message that can be recovered + /// \return the length of longest message that can be recovered, in bytes + /// \details MaxRecoverableLength() returns the length of longest message that can be recovered, or 0 if + /// this signature scheme does not support message recovery. + virtual size_t MaxRecoverableLength() const =0; + + /// \brief Provides the length of longest message that can be recovered from a signature of given length + /// \param signatureLength the length of the signature, in bytes + /// \return the length of longest message that can be recovered from a signature of given length, in bytes + /// \details MaxRecoverableLengthFromSignatureLength() returns the length of longest message that can be + /// recovered from a signature of given length, or 0 if this signature scheme does not support message + /// recovery. + virtual size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const =0; + + /// \brief Determines whether a signature scheme requires a random number generator + /// \return true if the signature scheme requires a RandomNumberGenerator() to sign + /// \details if IsProbabilistic() returns false, then NullRNG() can be passed to functions that take + /// RandomNumberGenerator(). + virtual bool IsProbabilistic() const =0; + + /// \brief Determines whether the non-recoverable message part can be signed + /// \return true if the non-recoverable message part can be signed + virtual bool AllowNonrecoverablePart() const =0; + + /// \brief Determines whether the signature must be input before the message + /// \return true if the signature must be input before the message during verifcation + /// \details if SignatureUpfront() returns true, then you must input the signature before the message + /// during verification. Otherwise you can input the signature at anytime. + virtual bool SignatureUpfront() const {return false;} + + /// \brief Determines whether the recoverable part must be input before the non-recoverable part + /// \return true if the recoverable part must be input before the non-recoverable part during signing + /// \details RecoverablePartFirst() determines whether you must input the recoverable part before the + /// non-recoverable part during signing + virtual bool RecoverablePartFirst() const =0; +}; + +/// \brief Interface for accumulating messages to be signed or verified +/// \details Only Update() should be called from the PK_MessageAccumulator() class. No other functions +/// inherited from HashTransformation, like DigestSize() and TruncatedFinal(), should be called. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation +{ +public: + /// \warning DigestSize() should not be called on PK_MessageAccumulator + unsigned int DigestSize() const + {throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");} + + /// \warning TruncatedFinal() should not be called on PK_MessageAccumulator + void TruncatedFinal(byte *digest, size_t digestSize) + { + CRYPTOPP_UNUSED(digest); CRYPTOPP_UNUSED(digestSize); + throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called"); + } +}; + +/// \brief Interface for public-key signers +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm +{ +public: + virtual ~PK_Signer() {} + + /// \brief Create a new HashTransformation to accumulate the message to be signed + /// \param rng a RandomNumberGenerator derived class + /// \return a pointer to a PK_MessageAccumulator + /// \details NewSignatureAccumulator() can be used with all signing methods. Sign() will automatically delete the + /// accumulator pointer. The caller is responsible for deletion if a method is called that takes a reference. + virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0; + + /// \brief Input a recoverable message to an accumulator + /// \param messageAccumulator a reference to a PK_MessageAccumulator + /// \param recoverableMessage a pointer to the recoverable message part to be signed + /// \param recoverableMessageLength the size of the recoverable message part + virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const =0; + + /// \brief Sign and delete the messageAccumulator + /// \param rng a RandomNumberGenerator derived class + /// \param messageAccumulator a pointer to a PK_MessageAccumulator derived class + /// \param signature a block of bytes for the signature + /// \return actual signature length + /// \details Sign() deletes the messageAccumulator, even if an exception is thrown. + /// \pre COUNTOF(signature) == MaxSignatureLength() + virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const; + + /// \brief Sign and restart messageAccumulator + /// \param rng a RandomNumberGenerator derived class + /// \param messageAccumulator a pointer to a PK_MessageAccumulator derived class + /// \param signature a block of bytes for the signature + /// \param restart flag indicating whether the messageAccumulator should be restarted + /// \return actual signature length + /// \pre COUNTOF(signature) == MaxSignatureLength() + virtual size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0; + + /// \brief Sign a message + /// \param rng a RandomNumberGenerator derived class + /// \param message a pointer to the message + /// \param messageLen the size of the message to be signed + /// \param signature a block of bytes for the signature + /// \return actual signature length + /// \pre COUNTOF(signature) == MaxSignatureLength() + virtual size_t SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const; + + /// \brief Sign a recoverable message + /// \param rng a RandomNumberGenerator derived class + /// \param recoverableMessage a pointer to the recoverable message part to be signed + /// \param recoverableMessageLength the size of the recoverable message part + /// \param nonrecoverableMessage a pointer to the non-recoverable message part to be signed + /// \param nonrecoverableMessageLength the size of the non-recoverable message part + /// \param signature a block of bytes for the signature + /// \return actual signature length + /// \pre COUNTOF(signature) == MaxSignatureLength(recoverableMessageLength) + virtual size_t SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const; +}; + +/// \brief Interface for public-key signature verifiers +/// \details The Recover* functions throw NotImplemented if the signature scheme does not support +/// message recovery. +/// \details The Verify* functions throw InvalidDataFormat if the scheme does support message +/// recovery and the signature contains a non-empty recoverable message part. The +/// Recover* functions should be used in that case. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm +{ +public: + virtual ~PK_Verifier() {} + + /// \brief Create a new HashTransformation to accumulate the message to be verified + /// \return a pointer to a PK_MessageAccumulator + /// \details NewVerificationAccumulator() can be used with all verification methods. Verify() will automatically delete + /// the accumulator pointer. The caller is responsible for deletion if a method is called that takes a reference. + virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0; + + /// \brief Input signature into a message accumulator + /// \param messageAccumulator a pointer to a PK_MessageAccumulator derived class + /// \param signature the signature on the message + /// \param signatureLength the size of the signature + virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0; + + /// \brief Check whether messageAccumulator contains a valid signature and message + /// \param messageAccumulator a pointer to a PK_MessageAccumulator derived class + /// \return true if the signature is valid, false otherwise + /// \details Verify() deletes the messageAccumulator, even if an exception is thrown. + virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const; + + /// \brief Check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator + /// \param messageAccumulator a reference to a PK_MessageAccumulator derived class + /// \return true if the signature is valid, false otherwise + /// \details VerifyAndRestart() restarts the messageAccumulator + virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0; + + /// \brief Check whether input signature is a valid signature for input message + /// \param message a pointer to the message to be verified + /// \param messageLen the size of the message + /// \param signature a pointer to the signature over the message + /// \param signatureLen the size of the signature + /// \return true if the signature is valid, false otherwise + virtual bool VerifyMessage(const byte *message, size_t messageLen, + const byte *signature, size_t signatureLen) const; + + /// \brief Recover a message from its signature + /// \param recoveredMessage a pointer to the recoverable message part to be verified + /// \param messageAccumulator a pointer to a PK_MessageAccumulator derived class + /// \return the result of the verification operation + /// \details Recover() deletes the messageAccumulator, even if an exception is thrown. + /// \pre COUNTOF(recoveredMessage) == MaxRecoverableLengthFromSignatureLength(signatureLength) + virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const; + + /// \brief Recover a message from its signature + /// \param recoveredMessage a pointer to the recoverable message part to be verified + /// \param messageAccumulator a pointer to a PK_MessageAccumulator derived class + /// \return the result of the verification operation + /// \details RecoverAndRestart() restarts the messageAccumulator + /// \pre COUNTOF(recoveredMessage) == MaxRecoverableLengthFromSignatureLength(signatureLength) + virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0; + + /// \brief Recover a message from its signature + /// \param recoveredMessage a pointer for the recovered message + /// \param nonrecoverableMessage a pointer to the non-recoverable message part to be signed + /// \param nonrecoverableMessageLength the size of the non-recoverable message part + /// \param signature the signature on the message + /// \param signatureLength the size of the signature + /// \return the result of the verification operation + /// \pre COUNTOF(recoveredMessage) == MaxRecoverableLengthFromSignatureLength(signatureLength) + virtual DecodingResult RecoverMessage(byte *recoveredMessage, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, + const byte *signature, size_t signatureLength) const; +}; + +/// \brief Interface for domains of simple key agreement protocols +/// \details A key agreement domain is a set of parameters that must be shared +/// by two parties in a key agreement protocol, along with the algorithms +/// for generating key pairs and deriving agreed values. +/// \since Crypto++ 3.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyAgreementDomain : public KeyAgreementAlgorithm +{ +public: + virtual ~SimpleKeyAgreementDomain() {} + + /// \brief Provides the size of the agreed value + /// \return size of agreed value produced in this domain + virtual unsigned int AgreedValueLength() const =0; + + /// \brief Provides the size of the private key + /// \return size of private keys in this domain + virtual unsigned int PrivateKeyLength() const =0; + + /// \brief Provides the size of the public key + /// \return size of public keys in this domain + virtual unsigned int PublicKeyLength() const =0; + + /// \brief Generate 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 COUNTOF(privateKey) == PrivateKeyLength() + virtual void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; + + /// \brief Generate a 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 COUNTOF(publicKey) == PublicKeyLength() + virtual void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; + + /// \brief Generate a private/public key pair + /// \param rng a RandomNumberGenerator derived class + /// \param privateKey a byte buffer for the generated private key in this domain + /// \param publicKey a byte buffer for the generated public key in this domain + /// \details GenerateKeyPair() is equivalent to calling GeneratePrivateKey() and then GeneratePublicKey(). + /// \pre COUNTOF(privateKey) == PrivateKeyLength() + /// \pre COUNTOF(publicKey) == PublicKeyLength() + virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; + + /// \brief Derive agreed value + /// \param agreedValue a byte buffer for the shared secret + /// \param privateKey a byte buffer with your private key in this domain + /// \param otherPublicKey a byte buffer with the other party's public key in this domain + /// \param validateOtherPublicKey a flag indicating if the other party's public key should be validated + /// \return true upon success, false in case of failure + /// \details Agree() derives an agreed value from your private keys and couterparty's public keys. + /// \details The other party's public key is validated by default. If you have previously validated the + /// static public key, use validateStaticOtherPublicKey=false to save time. + /// \pre COUNTOF(agreedValue) == AgreedValueLength() + /// \pre COUNTOF(privateKey) == PrivateKeyLength() + /// \pre COUNTOF(otherPublicKey) == PublicKeyLength() + virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0; +}; + +/// \brief Interface for domains of authenticated key agreement protocols +/// \details In an authenticated key agreement protocol, each party has two +/// key pairs. The long-lived key pair is called the static key pair, +/// and the short-lived key pair is called the ephemeral key pair. +/// \since Crypto++ 3.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm +{ +public: + virtual ~AuthenticatedKeyAgreementDomain() {} + + /// \brief Provides the size of the agreed value + /// \return size of agreed value produced in this domain + virtual unsigned int AgreedValueLength() const =0; + + /// \brief Provides the size of the static private key + /// \return size of static private keys in this domain + virtual unsigned int StaticPrivateKeyLength() const =0; + + /// \brief Provides the size of the static public key + /// \return size of static public keys in this domain + virtual unsigned int StaticPublicKeyLength() const =0; + + /// \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 + /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength() + virtual void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; + + /// \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 + /// \pre COUNTOF(publicKey) == PublicStaticKeyLength() + virtual void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; + + /// \brief Generate a static private/public key pair + /// \param rng a RandomNumberGenerator derived class + /// \param privateKey a byte buffer for the generated private key in this domain + /// \param publicKey a byte buffer for the generated public key in this domain + /// \details GenerateStaticKeyPair() is equivalent to calling GenerateStaticPrivateKey() and then GenerateStaticPublicKey(). + /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength() + /// \pre COUNTOF(publicKey) == PublicStaticKeyLength() + virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; + + /// \brief Provides the size of ephemeral private key + /// \return the size of ephemeral private key in this domain + virtual unsigned int EphemeralPrivateKeyLength() const =0; + + /// \brief Provides the size of ephemeral public key + /// \return the size of ephemeral public key in this domain + virtual unsigned int EphemeralPublicKeyLength() const =0; + + /// \brief Generate ephemeral private key + /// \param rng a RandomNumberGenerator derived class + /// \param privateKey a byte buffer for the generated private key in this domain + /// \pre COUNTOF(privateKey) == PrivateEphemeralKeyLength() + virtual void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; + + /// \brief Generate ephemeral public key + /// \param rng a RandomNumberGenerator derived class + /// \param privateKey a byte buffer for the generated private key in this domain + /// \param publicKey a byte buffer for the generated public key in this domain + /// \pre COUNTOF(publicKey) == PublicEphemeralKeyLength() + virtual void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; + + /// \brief Generate private/public key pair + /// \param rng a RandomNumberGenerator derived class + /// \param privateKey a byte buffer for the generated private key in this domain + /// \param publicKey a byte buffer for the generated public key in this domain + /// \details GenerateEphemeralKeyPair() is equivalent to calling GenerateEphemeralPrivateKey() and then GenerateEphemeralPublicKey() + virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; + + /// \brief Derive agreed value + /// \param agreedValue a byte buffer for the shared secret + /// \param staticPrivateKey a byte buffer with your static private key in this domain + /// \param ephemeralPrivateKey a byte buffer with your ephemeral private key in this domain + /// \param staticOtherPublicKey a byte buffer with the other party's static public key in this domain + /// \param ephemeralOtherPublicKey a byte buffer with the other party's ephemeral public key in this domain + /// \param validateStaticOtherPublicKey a flag indicating if the other party's public key should be validated + /// \return true upon success, false in case of failure + /// \details Agree() derives an agreed value from your private keys and couterparty's public keys. + /// \details The other party's ephemeral public key is validated by default. If you have previously validated + /// the static public key, use validateStaticOtherPublicKey=false to save time. + /// \pre COUNTOF(agreedValue) == AgreedValueLength() + /// \pre COUNTOF(staticPrivateKey) == StaticPrivateKeyLength() + /// \pre COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength() + /// \pre COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength() + /// \pre COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength() + virtual bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const =0; +}; + +// interface for password authenticated key agreement protocols, not implemented yet +#if 0 +/// \brief Interface for protocol sessions +/*! The methods should be called in the following order: + + InitializeSession(rng, parameters); // or call initialize method in derived class + while (true) + { + if (OutgoingMessageAvailable()) + { + length = GetOutgoingMessageLength(); + GetOutgoingMessage(message); + ; // send outgoing message + } + + if (LastMessageProcessed()) + break; + + ; // receive incoming message + ProcessIncomingMessage(message); + } + ; // call methods in derived class to obtain result of protocol session +*/ +class ProtocolSession +{ +public: + /// Exception thrown when an invalid protocol message is processed + class ProtocolError : public Exception + { + public: + ProtocolError(ErrorType errorType, const std::string &s) : Exception(errorType, s) {} + }; + + /// Exception thrown when a function is called unexpectedly + /*! for example calling ProcessIncomingMessage() when ProcessedLastMessage() == true */ + class UnexpectedMethodCall : public Exception + { + public: + UnexpectedMethodCall(const std::string &s) : Exception(OTHER_ERROR, s) {} + }; + + virtual ~ProtocolSession() {} + + ProtocolSession() : m_rng(NULLPTR), m_throwOnProtocolError(true), m_validState(false) {} + + virtual void InitializeSession(RandomNumberGenerator &rng, const NameValuePairs ¶meters) =0; + + bool GetThrowOnProtocolError() const {return m_throwOnProtocolError;} + void SetThrowOnProtocolError(bool throwOnProtocolError) {m_throwOnProtocolError = throwOnProtocolError;} + + bool HasValidState() const {return m_validState;} + + virtual bool OutgoingMessageAvailable() const =0; + virtual unsigned int GetOutgoingMessageLength() const =0; + virtual void GetOutgoingMessage(byte *message) =0; + + virtual bool LastMessageProcessed() const =0; + virtual void ProcessIncomingMessage(const byte *message, unsigned int messageLength) =0; + +protected: + void HandleProtocolError(Exception::ErrorType errorType, const std::string &s) const; + void CheckAndHandleInvalidState() const; + void SetValidState(bool valid) {m_validState = valid;} + + RandomNumberGenerator *m_rng; + +private: + bool m_throwOnProtocolError, m_validState; +}; + +class KeyAgreementSession : public ProtocolSession +{ +public: + virtual ~KeyAgreementSession() {} + + virtual unsigned int GetAgreedValueLength() const =0; + virtual void GetAgreedValue(byte *agreedValue) const =0; +}; + +class PasswordAuthenticatedKeyAgreementSession : public KeyAgreementSession +{ +public: + virtual ~PasswordAuthenticatedKeyAgreementSession() {} + + void InitializePasswordAuthenticatedKeyAgreementSession(RandomNumberGenerator &rng, + const byte *myId, unsigned int myIdLength, + const byte *counterPartyId, unsigned int counterPartyIdLength, + const byte *passwordOrVerifier, unsigned int passwordOrVerifierLength); +}; + +/// \brief Password based key agreement domain +/// \since Crypto++ 3.0 +class PasswordAuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm +{ +public: + virtual ~PasswordAuthenticatedKeyAgreementDomain() {} + + /// return whether the domain parameters stored in this object are valid + virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const + {return GetCryptoParameters().Validate(rng, 2);} + + virtual unsigned int GetPasswordVerifierLength(const byte *password, unsigned int passwordLength) const =0; + virtual void GeneratePasswordVerifier(RandomNumberGenerator &rng, const byte *userId, unsigned int userIdLength, const byte *password, unsigned int passwordLength, byte *verifier) const =0; + + enum RoleFlags {CLIENT=1, SERVER=2, INITIATOR=4, RESPONDER=8}; + + virtual bool IsValidRole(unsigned int role) =0; + virtual PasswordAuthenticatedKeyAgreementSession * CreateProtocolSession(unsigned int role) const =0; +}; +#endif + +/// \brief Exception thrown when an ASN.1 BER decoing error is encountered +class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument +{ +public: + BERDecodeErr() : InvalidArgument("BER decode error") {} + BERDecodeErr(const std::string &s) : InvalidArgument(s) {} +}; + +/// \brief Interface for encoding and decoding ASN1 objects +/// \details Each class that derives from ASN1Object should provide a serialization format +/// that controls subobject layout. Most of the time the serialization format is +/// taken from a standard, like P1363 or an RFC. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object +{ +public: + virtual ~ASN1Object() {} + + /// \brief Decode this object from a BufferedTransformation + /// \param bt BufferedTransformation object + /// \details Uses Basic Encoding Rules (BER) + virtual void BERDecode(BufferedTransformation &bt) =0; + + /// \brief Encode this object into a BufferedTransformation + /// \param bt BufferedTransformation object + /// \details Uses Distinguished Encoding Rules (DER) + virtual void DEREncode(BufferedTransformation &bt) const =0; + + /// \brief Encode this object into a BufferedTransformation + /// \param bt BufferedTransformation object + /// \details Uses Basic Encoding Rules (BER). + /// \details This may be useful if DEREncode() would be too inefficient. + virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);} +}; + +/// \brief Specifies the build-time version of the library +/// \return integer representing the build-time version +/// \details LibraryVersion can help detect inadvertent mixing and matching of library +/// versions. When using Crypto++ distributed by a third party, LibraryVersion() +/// records the version of the shared object that was built by the third party. +/// The LibraryVersion() record resides in cryptlib.o on Unix compatibles +/// and cryptlib.obj on Windows. It does not change when an app links +/// to the library. +/// \details LibraryVersion() is declared with C linkage (extern "C") within the +/// CryptoPP namespace to help programs locate the symbol. If the symbol is present, then +/// the library version is 5.7 or above. If it is missing, then the library version is +/// 5.6.5 or below. +/// \details The function could be used as shown below. +///
  if (LibraryVersion() != HeaderVersion())
+///   {
+///      cout << "Potential version mismatch" << endl;
+///
+///      const int lmaj = (LibraryVersion() / 100U) % 10;
+///      const int lmin = (LibraryVersion() / 10U) % 10;
+///      const int hmaj = (HeaderVersion() / 100U) % 10;
+///      const int hmin = (HeaderVersion() / 10U) % 10;
+///
+///      if(lmaj != hmaj)
+///         cout << "Major version mismatch" << endl;
+///      else if(lmin != hmin)
+///         cout << "Minor version mismatch" << endl;
+///   }
+/// 
+/// \sa HeaderVersion(), GitHub Issue 371. +/// \since Crypto++ 6.0 +extern "C" { + int LibraryVersion(CRYPTOPP_NOINLINE_DOTDOTDOT); +} // C linkage + +/// \brief Specifies the runtime version of the library +/// \return integer representing the runtime version +/// \details HeaderVersion() can help detect inadvertent mixing and matching of library +/// versions. When using Crypto++ distributed by a third party, HeaderVersion() +/// records the version of the headers used by the app when the app is compiled. +/// \details HeaderVersion() is declared with C linkage (extern "C") within the +/// CryptoPP namespace to help programs locate the symbol. If the symbol is present, then +/// the library version is 5.7 or above. If it is missing, then the library version is +/// 5.6.5 or below. +/// \details The function could be used as shown below. +///
  if (LibraryVersion() != HeaderVersion())
+///   {
+///      cout << "Potential version mismatch" << endl;
+///
+///      const int lmaj = (LibraryVersion() / 100U) % 10;
+///      const int lmin = (LibraryVersion() / 10U) % 10;
+///      const int hmaj = (HeaderVersion() / 100U) % 10;
+///      const int hmin = (HeaderVersion() / 10U) % 10;
+///
+///      if(lmaj != hmaj)
+///         cout << "Major version mismatch" << endl;
+///      else if(lmin != hmin)
+///         cout << "Minor version mismatch" << endl;
+///   }
+/// 
+/// \sa LibraryVersion(), GitHub Issue 371. +/// \since Crypto++ 6.0 +extern "C" { +inline int HeaderVersion() +{ + return CRYPTOPP_VERSION; +} +} // C linkage + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/darn.h b/third_party/cryptoppwin/include/cryptopp/darn.h new file mode 100644 index 00000000..41062b32 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 Power +/// ISA Version 3.0B +/// \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 darn 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 Power +/// ISA Version 3.0B, 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 > m_temp; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_DARN_H diff --git a/third_party/cryptoppwin/include/cryptopp/default.h b/third_party/cryptoppwin/include/cryptopp/default.h new file mode 100644 index 00000000..cb24afb7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/default.h @@ -0,0 +1,310 @@ +// default.h - originally written and placed in the public domain by Wei Dai + +/// \file default.h +/// \brief Classes for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC + +#ifndef CRYPTOPP_DEFAULT_H +#define CRYPTOPP_DEFAULT_H + +#include "sha.h" +#include "hmac.h" +#include "aes.h" +#include "des.h" +#include "modes.h" +#include "filters.h" +#include "smartptr.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Legacy block cipher for LegacyEncryptor, LegacyDecryptor, LegacyEncryptorWithMAC and LegacyDecryptorWithMAC +typedef DES_EDE2 LegacyBlockCipher; +/// \brief Legacy hash for use with LegacyEncryptorWithMAC and LegacyDecryptorWithMAC +typedef SHA1 LegacyHashModule; +/// \brief Legacy HMAC for use withLegacyEncryptorWithMAC and LegacyDecryptorWithMAC +typedef HMAC LegacyMAC; + +/// \brief Default block cipher for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC +typedef AES DefaultBlockCipher; +/// \brief Default hash for use with DefaultEncryptorWithMAC and DefaultDecryptorWithMAC +typedef SHA256 DefaultHashModule; +/// \brief Default HMAC for use withDefaultEncryptorWithMAC and DefaultDecryptorWithMAC +typedef HMAC DefaultMAC; + +/// \brief Exception thrown when LegacyDecryptorWithMAC or DefaultDecryptorWithMAC decryption error is encountered +class DataDecryptorErr : public Exception +{ +public: + DataDecryptorErr(const std::string &s) + : Exception(DATA_INTEGRITY_CHECK_FAILED, s) {} +}; + +/// \brief Exception thrown when a bad key is encountered in DefaultDecryptorWithMAC and LegacyDecryptorWithMAC +class KeyBadErr : public DataDecryptorErr +{ + public: KeyBadErr() + : DataDecryptorErr("DataDecryptor: cannot decrypt message with this passphrase") {} +}; + +/// \brief Exception thrown when an incorrect MAC is encountered in DefaultDecryptorWithMAC and LegacyDecryptorWithMAC +class MACBadErr : public DataDecryptorErr +{ + public: MACBadErr() + : DataDecryptorErr("DataDecryptorWithMAC: MAC check failed") {} +}; + +/// \brief Algorithm information for password-based encryptors and decryptors +template +struct DataParametersInfo +{ + CRYPTOPP_CONSTANT(BLOCKSIZE = BlockSize); + CRYPTOPP_CONSTANT(KEYLENGTH = KeyLength); + CRYPTOPP_CONSTANT(SALTLENGTH = SaltSize); + CRYPTOPP_CONSTANT(DIGESTSIZE = DigestSize); + CRYPTOPP_CONSTANT(ITERATIONS = Iterations); +}; + +typedef DataParametersInfo LegacyParametersInfo; +typedef DataParametersInfo DefaultParametersInfo; + +/// \brief Password-based Encryptor +/// \tparam BC BlockCipher based class used for encryption +/// \tparam H HashTransformation based class used for mashing +/// \tparam Info Constants used by the algorithms +/// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1. +/// Crypto++ 5.7 switched to AES and SHA256. +/// \sa DefaultEncryptor, DefaultDecryptor, LegacyEncryptor, LegacyDecryptor +/// \since Crypto++ 2.0 +template +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); + + /// \brief Construct a DataEncryptor + /// \param passphrase a C-String password + /// \param attachment a BufferedTransformation to attach to this object + DataEncryptor(const char *passphrase, BufferedTransformation *attachment = NULLPTR); + + /// \brief Construct a DataEncryptor + /// \param passphrase a byte string password + /// \param passphraseLength the length of the byte string password + /// \param attachment a BufferedTransformation to attach to this object + DataEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULLPTR); + +protected: + void FirstPut(const byte *); + void LastPut(const byte *inString, size_t length); + +private: + SecByteBlock m_passphrase; + typename CBC_Mode::Encryption m_cipher; +}; + +/// \brief Password-based Decryptor +/// \tparam BC BlockCipher based class used for encryption +/// \tparam H HashTransformation based class used for mashing +/// \tparam Info Constants used by the algorithms +/// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1. +/// Crypto++ 5.7 switched to AES and SHA256. +/// \sa DefaultEncryptor, DefaultDecryptor, LegacyEncryptor, LegacyDecryptor +/// \since Crypto++ 2.0 +template +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); + + /// \brief Constructs a DataDecryptor + /// \param passphrase a C-String password + /// \param attachment a BufferedTransformation to attach to this object + /// \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 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}; + State CurrentState() const {return m_state;} + +protected: + void FirstPut(const byte *inString); + void LastPut(const byte *inString, size_t length); + + State m_state; + +private: + void CheckKey(const byte *salt, const byte *keyCheck); + + SecByteBlock m_passphrase; + typename CBC_Mode::Decryption m_cipher; + member_ptr m_decryptor; + bool m_throwException; + +}; + +/// \brief Password-based encryptor with MAC +/// \tparam BC BlockCipher based class used for encryption +/// \tparam H HashTransformation based class used for mashing +/// \tparam MAC HashTransformation based class used for authentication +/// \tparam Info Constants used by the algorithms +/// \details DataEncryptorWithMAC uses a non-standard mashup function called Mash() to derive key +/// bits from the password. +/// \details The purpose of the function Mash() is to take an arbitrary length input string and +/// *deterministically* produce an arbitrary length output string such that (1) it looks random, +/// (2) no information about the input is deducible from it, and (3) it contains as much entropy +/// as it can hold, or the amount of entropy in the input string, whichever is smaller. +/// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1. +/// Crypto++ 5.7 switched to AES and SHA256. +/// \sa DefaultEncryptorWithMAC, DefaultDecryptorWithMAC, LegacyDecryptorWithMAC, LegacyEncryptorWithMAC +/// \since Crypto++ 2.0 +template +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); + + /// \brief Constructs a DataEncryptorWithMAC + /// \param passphrase a C-String password + /// \param attachment a BufferedTransformation to attach to this object + DataEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULLPTR); + + /// \brief Constructs a DataEncryptorWithMAC + /// \param passphrase a byte string password + /// \param passphraseLength the length of the byte string password + /// \param attachment a BufferedTransformation to attach to this object + DataEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULLPTR); + +protected: + void FirstPut(const byte *inString) {CRYPTOPP_UNUSED(inString);} + void LastPut(const byte *inString, size_t length); + +private: + member_ptr m_mac; + +}; + +/// \brief Password-based decryptor with MAC +/// \tparam BC BlockCipher based class used for encryption +/// \tparam H HashTransformation based class used for mashing +/// \tparam MAC HashTransformation based class used for authentication +/// \tparam Info Constants used by the algorithms +/// \details DataDecryptorWithMAC uses a non-standard mashup function called Mash() to derive key +/// bits from the password. +/// \details The purpose of the function Mash() is to take an arbitrary length input string and +/// *deterministically* produce an arbitrary length output string such that (1) it looks random, +/// (2) no information about the input is deducible from it, and (3) it contains as much entropy +/// as it can hold, or the amount of entropy in the input string, whichever is smaller. +/// \details Crypto++ 5.6.5 and earlier used the legacy algorithms, including DES_EDE2 and SHA1. +/// Crypto++ 5.7 switched to AES and SHA256. +/// \sa DefaultEncryptorWithMAC, DefaultDecryptorWithMAC, LegacyDecryptorWithMAC, LegacyEncryptorWithMAC +/// \since Crypto++ 2.0 +template +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); + + /// \brief Constructs a DataDecryptor + /// \param passphrase a C-String password + /// \param attachment a BufferedTransformation to attach to this object + /// \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 specifying whether an Exception should be thrown on error + DataDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULLPTR, bool throwException=true); + + typename DataDecryptor::State CurrentState() const; + bool CheckLastMAC() const; + +protected: + void FirstPut(const byte *inString) {CRYPTOPP_UNUSED(inString);} + void LastPut(const byte *inString, size_t length); + +private: + member_ptr m_mac; + HashVerificationFilter *m_hashVerifier; + bool m_throwException; +}; + +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) +/// \brief Password-based encryptor (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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct LegacyEncryptor : public DataEncryptor {}; +/// \brief Password-based decryptor (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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct LegacyDecryptor : public DataDecryptor {}; +/// \brief Password-based encryptor +/// \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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct DefaultEncryptor : public DataEncryptor {}; +/// \brief Password-based decryptor +/// \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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct DefaultDecryptor : public DataDecryptor {}; +/// \brief Password-based encryptor 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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct LegacyEncryptorWithMAC : public DataEncryptorWithMAC {}; +/// \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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct LegacyDecryptorWithMAC : public DataDecryptorWithMAC {}; +/// \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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct DefaultEncryptorWithMAC : public DataEncryptorWithMAC {}; +/// \brief Password-based decryptor 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 +/// Default* classes, and the old algorithms are available with the Legacy* classes. +struct DefaultDecryptorWithMAC : public DataDecryptorWithMAC {}; +#else +typedef DataEncryptor LegacyEncryptor; +typedef DataDecryptor LegacyDecryptor; + +typedef DataEncryptor DefaultEncryptor; +typedef DataDecryptor DefaultDecryptor; + +typedef DataEncryptorWithMAC LegacyEncryptorWithMAC; +typedef DataDecryptorWithMAC LegacyDecryptorWithMAC; + +typedef DataEncryptorWithMAC DefaultEncryptorWithMAC; +typedef DataDecryptorWithMAC DefaultDecryptorWithMAC; +#endif + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/des.h b/third_party/cryptoppwin/include/cryptopp/des.h new file mode 100644 index 00000000..10ba0598 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/des.h @@ -0,0 +1,163 @@ +// des.h - originally written and placed in the public domain by Wei Dai + +/// \file des.h +/// \brief Classes for DES, 2-key Triple-DES, 3-key Triple-DES and DESX + +#ifndef CRYPTOPP_DES_H +#define CRYPTOPP_DES_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief DES block cipher base class +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL RawDES +{ +public: + void RawSetKey(CipherDir direction, const byte *userKey); + void RawProcessBlock(word32 &l, word32 &r) const; + +protected: + static const word32 Spbox[8][64]; + + FixedSizeSecBlock k; +}; + +/// \brief DES block cipher information +/// \since Crypto++ 1.0 +struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8> +{ + // disable DES in DLL version by not exporting this function + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "DES";} +}; + +/// \brief DES block cipher +/// \details The DES implementation in Crypto++ ignores the parity bits +/// (the least significant bits of each byte) in the key. However you can use CheckKeyParityBits() +/// and CorrectKeyParityBits() to check or correct the parity bits if you wish. +/// \sa DES +/// \since Crypto++ 1.0 +class DES : public DES_Info, public BlockCipherDocumentation +{ + /// \brief DES block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl, public RawDES + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + /// check DES key parity bits + static bool CheckKeyParityBits(const byte *key); + /// correct DES key parity bits + static void CorrectKeyParityBits(byte *key); + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief 2-key TripleDES block cipher information +/// \since Crypto++ 1.0 +struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";} +}; + +/// \brief 2-key TripleDES block cipher +/// \sa DES-EDE2 +/// \since Crypto++ 1.0 +class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation +{ + /// \brief DES_EDE2 block cipher default operation + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + RawDES m_des1, m_des2; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief 3-key TripleDES block cipher information +/// \since Crypto++ 1.0 +struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";} +}; + +/// \brief 3-key TripleDES block cipher +/// \sa DES-EDE3 +/// \since Crypto++ 1.0 +class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation +{ + /// \brief DES_EDE3 block cipher default operation + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + RawDES m_des1, m_des2, m_des3; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief DESX block cipher information +/// \since Crypto++ 3.2 +struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "DES-XEX3";} +}; + +/// \brief DESX block cipher +/// \sa DES-XEX3, AKA DESX +/// \since Crypto++ 3.2 +class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation +{ + /// \brief DES_XEX3 block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + FixedSizeSecBlock m_x1, m_x3; + // VS2005 workaround: calling modules compiled with /clr gets unresolved external symbol DES::Base::ProcessAndXorBlock + // if we use DES::Encryption here directly without value_ptr. + value_ptr m_des; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef DES::Encryption DESEncryption; +typedef DES::Decryption DESDecryption; + +typedef DES_EDE2::Encryption DES_EDE2_Encryption; +typedef DES_EDE2::Decryption DES_EDE2_Decryption; + +typedef DES_EDE3::Encryption DES_EDE3_Encryption; +typedef DES_EDE3::Decryption DES_EDE3_Decryption; + +typedef DES_XEX3::Encryption DES_XEX3_Encryption; +typedef DES_XEX3::Decryption DES_XEX3_Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/dh.h b/third_party/cryptoppwin/include/cryptopp/dh.h new file mode 100644 index 00000000..e12adba1 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/dh.h @@ -0,0 +1,275 @@ +// dh.h - originally written and placed in the public domain by Wei Dai + +/// \file dh.h +/// \brief Classes for Diffie-Hellman key exchange + +#ifndef CRYPTOPP_DH_H +#define CRYPTOPP_DH_H + +#include "cryptlib.h" +#include "gfpcrypt.h" +#include "algebra.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Diffie-Hellman domain +/// \tparam GROUP_PARAMETERS group parameters +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \details A Diffie-Hellman domain is a set of parameters that must be shared +/// by two parties in a key agreement protocol, along with the algorithms +/// for generating key pairs and deriving agreed values. +/// \details For COFACTOR_OPTION, see CofactorMultiplicationOption. +/// \sa DL_SimpleKeyAgreementDomainBase +/// \since Crypto++ 1.0 +template +class DH_Domain : public DL_SimpleKeyAgreementDomainBase +{ + typedef DL_SimpleKeyAgreementDomainBase Base; + +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef DL_KeyAgreementAlgorithm_DH DH_Algorithm; + typedef DH_Domain Domain; + + virtual ~DH_Domain() {} + + /// \brief Construct a Diffie-Hellman domain + DH_Domain() {} + + /// \brief Construct a Diffie-Hellman domain + /// \param params group parameters and options + DH_Domain(const GroupParameters ¶ms) + : m_groupParameters(params) {} + + /// \brief Construct a Diffie-Hellman domain + /// \param bt BufferedTransformation with group parameters and options + DH_Domain(BufferedTransformation &bt) + {m_groupParameters.BERDecode(bt);} + + /// \brief Create a Diffie-Hellman domain + /// \tparam T2 template parameter used as a constructor parameter + /// \param v1 RandomNumberGenerator derived class + /// \param v2 second parameter + /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object. + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2) + {m_groupParameters.Initialize(v1, v2);} + + /// \brief Create a Diffie-Hellman domain + /// \tparam T2 template parameter used as a constructor parameter + /// \tparam T3 template parameter used as a constructor parameter + /// \param v1 RandomNumberGenerator derived class + /// \param v2 second parameter + /// \param v3 third parameter + /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object. + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + /// \brief Create a Diffie-Hellman domain + /// \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 RandomNumberGenerator derived class + /// \param v2 second parameter + /// \param v3 third parameter + /// \param v4 fourth parameter + /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object. + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + /// \brief Construct a Diffie-Hellman 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 + /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object. + template + DH_Domain(const T1 &v1, const T2 &v2) + {m_groupParameters.Initialize(v1, v2);} + + /// \brief Construct a Diffie-Hellman 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 + /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object. + template + DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + /// \brief Construct a Diffie-Hellman 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 fourth parameter + /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object. + template + DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + /// \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;} + /// \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 Generate a public key from a private key in this domain + /// \param rng RandomNumberGenerator derived class + /// \param privateKey byte buffer with the previously generated private key + /// \param publicKey byte buffer for the generated public key in this domain + /// \details If using a FIPS 140-2 validated library on Windows, then this class will perform + /// a self test to ensure the key pair is pairwise consistent. Non-FIPS and non-Windows + /// builds of the library do not provide FIPS validated cryptography, so the code should be + /// removed by the optimizer. + /// \pre COUNTOF(publicKey) == PublicKeyLength() + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + Base::GeneratePublicKey(rng, privateKey, publicKey); + + if (FIPS_140_2_ComplianceEnabled()) + { + SecByteBlock privateKey2(this->PrivateKeyLength()); + this->GeneratePrivateKey(rng, privateKey2); + + SecByteBlock publicKey2(this->PublicKeyLength()); + Base::GeneratePublicKey(rng, privateKey2, publicKey2); + + SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength()); + bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2); + bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey); + + if (!agreed1 || !agreed2 || agreedValue != agreedValue2) + throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed"); + } + } + + static std::string CRYPTOPP_API StaticAlgorithmName() + {return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();} + std::string AlgorithmName() const {return StaticAlgorithmName();} + +private: + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const + {return Singleton().Ref();} + DL_GroupParameters & AccessAbstractGroupParameters() + {return m_groupParameters;} + + GroupParameters m_groupParameters; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain; + +/// \brief Diffie-Hellman in GF(p) +/// \details DH() class is a typedef of DH_Domain(). The documentation that follows +/// does not exist. Rather the documentation was created in response to Issue +/// 328, Diffie-Hellman example code not compiling. +/// \details Generally speaking, a DH() object is ephemeral and is intended to execute one instance of the Diffie-Hellman protocol. The +/// private and public key parts are not intended to be set or persisted. Rather, a new set of domain parameters are generated each +/// time an object is created. +/// \details Once a DH() object is created, once can retrieve the ephemeral public key for the other party with code similar to the +/// following. +///
   AutoSeededRandomPool prng;
+///   Integer p, q, g;
+///   PrimeAndGenerator pg;
+///
+///   pg.Generate(1, prng, 512, 511);
+///   p = pg.Prime();
+///   q = pg.SubPrime();
+///   g = pg.Generator();
+///
+///   DH dh(p, q, g);
+///   SecByteBlock t1(dh.PrivateKeyLength()), t2(dh.PublicKeyLength());
+///   dh.GenerateKeyPair(prng, t1, t2);
+///   Integer k1(t1, t1.size()), k2(t2, t2.size());
+///
+///   cout << "Private key:\n";
+///   cout << hex << k1 << endl;
+///
+///   cout << "Public key:\n";
+///   cout << hex << k2 << endl;
+/// +/// \details Output of the program above will be similar to the following. +///
   $ ./cryptest.exe
+///   Private key:
+///   72b45a42371545e9d4880f48589aefh
+///   Public key:
+///   45fdb13f97b1840626f0250cec1dba4a23b894100b51fb5d2dd13693d789948f8bfc88f9200014b2
+///   ba8dd8a6debc471c69ef1e2326c61184a2eca88ec866346bh
+/// \sa Diffie-Hellman on the Crypto++ wiki and +/// Diffie-Hellman in GF(p) with key validation +/// \since Crypto++ 1.0 +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) +struct DH : public DH_Domain +{ + typedef DH_Domain GroupParameters; + typedef GroupParameters::Element Element; + + virtual ~DH() {} + + /// \brief Create an uninitialized Diffie-Hellman object + DH() : DH_Domain() {} + + /// \brief Initialize a Diffie-Hellman object + /// \param bt BufferedTransformation with group parameters and options + DH(BufferedTransformation &bt) : DH_Domain(bt) {} + + /// \brief Initialize a Diffie-Hellman object + /// \param params group parameters and options + DH(const GroupParameters ¶ms) : DH_Domain(params) {} + + /// \brief Create a Diffie-Hellman object + /// \param rng a RandomNumberGenerator derived class + /// \param modulusBits the size of the modulus, in bits + /// \details This function overload of Initialize() creates a new Diffie-Hellman object because it + /// takes a RandomNumberGenerator() as a parameter. + DH(RandomNumberGenerator &rng, unsigned int modulusBits) : DH_Domain(rng, modulusBits) {} + + /// \brief Initialize a Diffie-Hellman object + /// \param p the modulus + /// \param g the generator + DH(const Integer &p, const Integer &g) : DH_Domain(p, g) {} + + /// \brief Initialize a Diffie-Hellman object + /// \param p the modulus + /// \param q the subgroup order + /// \param g the generator + DH(const Integer &p, const Integer &q, const Integer &g) : DH_Domain(p, q, g) {} + + /// \brief Creates a Diffie-Hellman object + /// \param rng a RandomNumberGenerator derived class + /// \param modulusBits the size of the modulus, in bits + /// \details This function overload of Initialize() creates a new Diffie-Hellman object because it + /// takes a RandomNumberGenerator() as a parameter. + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) + {AccessGroupParameters().Initialize(rng, modulusBits);} + + /// \brief Initialize a Diffie-Hellman object + /// \param p the modulus + /// \param g the generator + void Initialize(const Integer &p, const Integer &g) + {AccessGroupParameters().Initialize(p, g);} + + /// \brief Initialize a Diffie-Hellman object + /// \param p the modulus + /// \param q the subgroup order + /// \param g the generator + void Initialize(const Integer &p, const Integer &q, const Integer &g) + {AccessGroupParameters().Initialize(p, q, g);} +}; +#else +// The real DH class is a typedef. +typedef DH_Domain DH; +#endif + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/dh2.h b/third_party/cryptoppwin/include/cryptopp/dh2.h new file mode 100644 index 00000000..6cbfe46b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/dh2.h @@ -0,0 +1,70 @@ +// dh2.h - originally written and placed in the public domain by Wei Dai + +/// \file dh2.h +/// \brief Classes for Unified Diffie-Hellman key exchange +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_DH2_H +#define CRYPTOPP_DH2_H + +#include "cryptlib.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Unified Diffie-Hellman in GF(p) +/// \details A Diffie-Hellman domain is a set of parameters that must be shared +/// by two parties in a key agreement protocol, along with the algorithms +/// for generating key pairs and deriving agreed values. +/// \sa AuthenticatedKeyAgreementDomain, Unified Diffie-Hellman +/// \since Crypto++ 3.0 +class DH2 : public AuthenticatedKeyAgreementDomain +{ +public: + virtual ~DH2() {} + + /// \brief Construct a DH2 + DH2(SimpleKeyAgreementDomain &domain) + : d1(domain), d2(domain) {} + /// \brief Construct a DH2 + DH2(SimpleKeyAgreementDomain &staticDomain, SimpleKeyAgreementDomain &ephemeralDomain) + : d1(staticDomain), d2(ephemeralDomain) {} + + CryptoParameters & AccessCryptoParameters() {return d1.AccessCryptoParameters();} + + unsigned int AgreedValueLength() const + {return d1.AgreedValueLength() + d2.AgreedValueLength();} + + unsigned int StaticPrivateKeyLength() const + {return d1.PrivateKeyLength();} + unsigned int StaticPublicKeyLength() const + {return d1.PublicKeyLength();} + void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + {d1.GeneratePrivateKey(rng, privateKey);} + void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + {d1.GeneratePublicKey(rng, privateKey, publicKey);} + void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const + {d1.GenerateKeyPair(rng, privateKey, publicKey);} + + unsigned int EphemeralPrivateKeyLength() const + {return d2.PrivateKeyLength();} + unsigned int EphemeralPublicKeyLength() const + {return d2.PublicKeyLength();} + void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + {d2.GeneratePrivateKey(rng, privateKey);} + void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + {d2.GeneratePublicKey(rng, privateKey, publicKey);} + void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const + {d2.GenerateKeyPair(rng, privateKey, publicKey);} + + bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const; + +protected: + SimpleKeyAgreementDomain &d1, &d2; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/dll.h b/third_party/cryptoppwin/include/cryptopp/dll.h new file mode 100644 index 00000000..1537ee6d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/dll.h @@ -0,0 +1,71 @@ +// dll.h - originally written and placed in the public domain by Wei Dai + +/// \file dll.h +/// \brief Functions and definitions required for building the FIPS-140 DLL on Windows + +#ifndef CRYPTOPP_DLL_H +#define CRYPTOPP_DLL_H + +#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL) +#ifdef CRYPTOPP_CONFIG_H +#error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files. +#endif +#define CRYPTOPP_IMPORTS +#endif + +#include "aes.h" +#include "cbcmac.h" +#include "ccm.h" +#include "cmac.h" +#include "channels.h" +#include "des.h" +#include "dh.h" +#include "dsa.h" +#include "ec2n.h" +#include "eccrypto.h" +#include "ecp.h" +#include "files.h" +#include "fips140.h" +#include "gcm.h" +#include "hex.h" +#include "hmac.h" +#include "modes.h" +#include "mqueue.h" +#include "nbtheory.h" +#include "osrng.h" +#include "pkcspad.h" +#include "pssr.h" +#include "randpool.h" +#include "rsa.h" +#include "rw.h" +#include "sha.h" +#include "skipjack.h" + +#ifdef CRYPTOPP_IMPORTS + +#ifdef _DLL +// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain() +#ifdef CRYPTOPP_DEBUG +# pragma comment(lib, "msvcrtd") +# pragma comment(lib, "cryptopp") +#else +# pragma comment(lib, "msvcrt") +# pragma comment(lib, "cryptopp") +#endif +#endif + +#endif // #ifdef CRYPTOPP_IMPORTS + +#include // for new_handler + +NAMESPACE_BEGIN(CryptoPP) + +typedef void * (CRYPTOPP_API * PNew)(size_t); +typedef void (CRYPTOPP_API * PDelete)(void *); +typedef void (CRYPTOPP_API * PGetNewAndDelete)(PNew &, PDelete &); +typedef std::new_handler (CRYPTOPP_API * PSetNewHandler)(std::new_handler); +typedef void (CRYPTOPP_API * PSetNewAndDelete)(PNew, PDelete, PSetNewHandler); + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/dmac.h b/third_party/cryptoppwin/include/cryptopp/dmac.h new file mode 100644 index 00000000..ef2fa189 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/dmac.h @@ -0,0 +1,114 @@ +// dmac.h - originally written and placed in the public domain by Wei Dai + +/// \file dmac.h +/// \brief Classes for DMAC message authentication code + +#ifndef CRYPTOPP_DMAC_H +#define CRYPTOPP_DMAC_H + +#include "cbcmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief DMAC message authentication code base class +/// \tparam T class derived from BlockCipherDocumentation +/// \since Crypto++ 3.1 +template +class CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs, public MessageAuthenticationCode +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE); + static std::string StaticAlgorithmName() {return std::string("DMAC(") + T::StaticAlgorithmName() + ")";} + + virtual~DMAC_Base() {} + DMAC_Base() : m_subkeylength(0), m_counter(0) {} + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void Update(const byte *input, size_t length); + 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); + + size_t m_subkeylength; + SecByteBlock m_subkeys; + CBC_MAC m_mac1; + typename T::Encryption m_f2; + unsigned int m_counter; +}; + +template +std::string DMAC_Base::AlgorithmProvider() const +{ + return m_f2.AlgorithmProvider(); +} + +/// \brief DMAC message authentication code +/// \tparam T class derived from BlockCipherDocumentation +/// \sa CBC MAC for Real-Time Data Sources (08.15.1997) +/// by Erez Petrank and Charles Rackoff +/// \since Crypto++ 3.1 +template +class DMAC : public MessageAuthenticationCodeFinal > +{ +public: + /// \brief Construct a DMAC + DMAC() {} + + /// \brief Construct a DMAC + /// \param key a byte array used to key the cipher + /// \param length the size of the byte array, in bytes + DMAC(const byte *key, size_t length=DMAC_Base::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} +}; + +template +void DMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + m_subkeylength = T::StaticGetValidKeyLength(T::BLOCKSIZE); + m_subkeys.resize(2*UnsignedMin((unsigned int)T::BLOCKSIZE, m_subkeylength)); + m_mac1.SetKey(GenerateSubKeys(key, length), m_subkeylength, params); + m_f2.SetKey(m_subkeys+m_subkeys.size()/2, m_subkeylength, params); + m_counter = 0; + m_subkeys.resize(0); +} + +template +void DMAC_Base::Update(const byte *input, size_t length) +{ + m_mac1.Update(input, length); + m_counter = (unsigned int)((m_counter + length) % T::BLOCKSIZE); +} + +template +void DMAC_Base::TruncatedFinal(byte *mac, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + byte pad[T::BLOCKSIZE]; + byte padByte = byte(T::BLOCKSIZE-m_counter); + std::memset(pad, padByte, padByte); + m_mac1.Update(pad, padByte); + m_mac1.TruncatedFinal(mac, size); + m_f2.ProcessBlock(mac); + + m_counter = 0; // reset for next message +} + +template +byte *DMAC_Base::GenerateSubKeys(const byte *key, size_t keylength) +{ + typename T::Encryption cipher(key, keylength); + 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); + return m_subkeys; +} + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/donna.h b/third_party/cryptoppwin/include/cryptopp/donna.h new file mode 100644 index 00000000..d37f2690 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 Donna +/// 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 +/// pubkey. +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 sharedKey. +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 publicKey. +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 diff --git a/third_party/cryptoppwin/include/cryptopp/donna_32.h b/third_party/cryptoppwin/include/cryptopp/donna_32.h new file mode 100644 index 00000000..50d6b820 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 diff --git a/third_party/cryptoppwin/include/cryptopp/donna_64.h b/third_party/cryptoppwin/include/cryptopp/donna_64.h new file mode 100644 index 00000000..3180d606 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 +# 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 diff --git a/third_party/cryptoppwin/include/cryptopp/donna_sse.h b/third_party/cryptoppwin/include/cryptopp/donna_sse.h new file mode 100644 index 00000000..581bf607 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 + +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 diff --git a/third_party/cryptoppwin/include/cryptopp/drbg.h b/third_party/cryptoppwin/include/cryptopp/drbg.h new file mode 100644 index 00000000..81920774 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/drbg.h @@ -0,0 +1,718 @@ +// drbg.h - written and placed in public domain by Jeffrey Walton. + +/// \file drbg.h +/// \brief Classes for NIST DRBGs from SP 800-90A +/// \sa Recommendation +/// for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015) +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_NIST_DRBG_H +#define CRYPTOPP_NIST_DRBG_H + +#include "cryptlib.h" +#include "secblock.h" +#include "hmac.h" +#include "sha.h" + +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 Recommendation +/// for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015) +/// \since Crypto++ 6.0 +class NIST_DRBG : public RandomNumberGenerator +{ +public: + /// \brief Exception thrown when a NIST DRBG encounters an error + class Err : public Exception + { + public: + explicit Err(const std::string &c, const std::string &m) + : Exception(OTHER_ERROR, c + ": " + m) {} + }; + +public: + virtual ~NIST_DRBG() {} + + /// \brief Determines if a generator can accept additional entropy + /// \return true + /// \details All NIST_DRBG return true + virtual bool CanIncorporateEntropy() const {return true;} + + /// \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 + /// \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 MINIMUM_ENTROPY entropy. The byte array for input must + /// meet NIST SP 800-90B or + /// SP 800-90C requirements. + virtual void IncorporateEntropy(const byte *input, size_t length)=0; + + /// \brief Update RNG state with additional unpredictable values + /// \param entropy the entropy to add to the generator + /// \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 + /// \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 + /// MINIMUM_ENTROPY entropy. The byte array for entropy must meet + /// NIST SP 800-90B or + ///! SP 800-90C 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 + /// \throw NIST_DRBG::Err if a reseed is required + /// \throw NIST_DRBG::Err if the size exceeds MAXIMUM_BYTES_PER_REQUEST + virtual void GenerateBlock(byte *output, size_t size)=0; + + /// \brief Generate random array of bytes + /// \param additional additional input to add to the generator + /// \param additionaLength the size of the additional input buffer + /// \param output the byte buffer + /// \param size the length of the buffer, in bytes + /// \throw NIST_DRBG::Err if a reseed is required + /// \throw NIST_DRBG::Err if the size exceeds MAXIMUM_BYTES_PER_REQUEST + /// \details GenerateBlock() is an overload provided to match NIST requirements. The byte + /// array for additional 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 + /// \return The security strength of the generator, in bytes + /// \details The equivalent class constant is SECURITY_STRENGTH + virtual unsigned int SecurityStrength() const=0; + + /// \brief Provides the seed length + /// \return The seed size of the generator, in bytes + /// \details The equivalent class constant is SEED_LENGTH. The size is + /// used to maintain internal state of V and C. + virtual unsigned int SeedLength() const=0; + + /// \brief Provides the minimum entropy size + /// \return The minimum entropy size required by the generator, in bytes + /// \details The equivalent class constant is MINIMUM_ENTROPY. All NIST DRBGs must + /// be instaniated with at least MINIMUM_ENTROPY bytes of entropy. The bytes must + /// meet NIST SP 800-90B or + /// SP 800-90C requirements. + virtual unsigned int MinEntropyLength() const=0; + + /// \brief Provides the maximum entropy size + /// \return The maximum entropy size that can be consumed by the generator, in bytes + /// \details The equivalent class constant is MAXIMUM_ENTROPY. The bytes must + /// meet NIST SP 800-90B or + /// SP 800-90C requirements. MAXIMUM_ENTROPY has been reduced from + /// 235 to INT_MAX to fit the underlying C++ datatype. + virtual unsigned int MaxEntropyLength() const=0; + + /// \brief Provides the minimum nonce size + /// \return The minimum nonce size recommended for the generator, in bytes + /// \details The equivalent class constant is MINIMUM_NONCE. If a nonce is not + /// required then MINIMUM_NONCE is 0. Hash_DRBG does not require a + /// nonce, while HMAC_DRBG and CTR_DRBG require a nonce. + virtual unsigned int MinNonceLength() const=0; + + /// \brief Provides the maximum nonce size + /// \return The maximum nonce that can be consumed by the generator, in bytes + /// \details The equivalent class constant is MAXIMUM_NONCE. MAXIMUM_NONCE + /// has been reduced from 235 to INT_MAX to fit the underlying C++ datatype. + /// If a nonce is not required then MINIMUM_NONCE is 0. Hash_DRBG does not + /// require a nonce, while HMAC_DRBG and CTR_DRBG require a nonce. + virtual unsigned int MaxNonceLength() const=0; + + /// \brief Provides the maximum size of a request to GenerateBlock + /// \return The maximum size of a request to GenerateBlock(), in bytes + /// \details The equivalent class constant is MAXIMUM_BYTES_PER_REQUEST + virtual unsigned int MaxBytesPerRequest() const=0; + + /// \brief Provides the maximum number of requests before a reseed + /// \return The maximum number of requests before a reseed, in bytes + /// \details The equivalent class constant is MAXIMUM_REQUESTS_BEFORE_RESEED. + /// MAXIMUM_REQUESTS_BEFORE_RESEED has been reduced from 248 to INT_MAX + /// to fit the underlying C++ datatype. + virtual unsigned int MaxRequestBeforeReseed() const=0; + +protected: + virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength, + const byte* nonce, size_t nonceLength, const byte* personalization, size_t personalizationLength)=0; + + virtual void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0; +}; + +// ************************************************************* + +/// \tparam HASH NIST approved hash derived from HashTransformation +/// \tparam STRENGTH security strength, in bytes +/// \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). +/// \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto +/// 248 requests before a reseed. However, Hash_DRBG limits it to INT_MAX 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 Recommendation +/// for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015) +/// \since Crypto++ 6.0 +template +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); + + static std::string StaticAlgorithmName() { return std::string("Hash_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); } + + /// \brief Construct a Hash DRBG + /// \param entropy the entropy to instantiate the generator + /// \param entropyLength the size of the entropy buffer + /// \param nonce additional input to instantiate the generator + /// \param nonceLength the size of the nonce buffer + /// \param personalization additional input to instantiate the generator + /// \param personalizationLength the size of the personalization buffer + /// \throw NIST_DRBG::Err if the generator is instantiated with insufficient entropy + /// \details All NIST DRBGs must be instaniated with at least MINIMUM_ENTROPY bytes of entropy. + /// The byte array for entropy must meet NIST + /// SP 800-90B or SP 800-90C requirements. + /// \details The nonce and personalization are optional byte arrays. If nonce is supplied, + /// then it should be at least MINIMUM_NONCE bytes of entropy. + /// \details An example of instantiating a SHA256 generator is shown below. + /// The example provides more entropy than required for SHA256. The NonblockingRng meets the + /// requirements of NIST SP 800-90B or SP 800-90C. + /// RDRAND() and RDSEED() generators would work as well. + ///
+    ///   SecByteBlock entropy(48), result(128);
+    ///   NonblockingRng prng;
+    ///   RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
+    ///
+    ///   Hash_DRBG drbg(entropy, 32, entropy+32, 16);
+    ///   drbg.GenerateBlock(result, result.size());
+    /// 
+ 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); + } + + unsigned int SecurityStrength() const {return SECURITY_STRENGTH;} + unsigned int SeedLength() const {return SEED_LENGTH;} + unsigned int MinEntropyLength() const {return MINIMUM_ENTROPY;} + unsigned int MaxEntropyLength() const {return MAXIMUM_ENTROPY;} + unsigned int MinNonceLength() const {return MINIMUM_NONCE;} + unsigned int MaxNonceLength() const {return MAXIMUM_NONCE;} + unsigned int MaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;} + unsigned int MaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;} + + void IncorporateEntropy(const byte *input, size_t length) + {return DRBG_Reseed(input, length, NULLPTR, 0);} + + void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength) + {return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);} + + void GenerateBlock(byte *output, size_t size) + {return Hash_Generate(NULLPTR, 0, output, size);} + + 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, + const byte* personalization, size_t personalizationLength); + + // 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.40) + void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength); + + // 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.41) + void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size); + + // 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.49) + void 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); + +private: + HASH m_hash; + SecByteBlock m_c, m_v, m_temp; + word64 m_reseed; +}; + +// typedef Hash_DRBG Hash_SHA1_DRBG; +// typedef Hash_DRBG Hash_SHA256_DRBG; +// typedef Hash_DRBG Hash_SHA384_DRBG; +// typedef Hash_DRBG Hash_SHA512_DRBG; + +// ************************************************************* + +/// \tparam HASH NIST approved hash derived from HashTransformation +/// \tparam STRENGTH security strength, in bytes +/// \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). +/// \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto 248 requests +/// before a reseed. However, HMAC_DRBG limits it to INT_MAX 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 Recommendation +/// for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015) +/// \since Crypto++ 6.0 +template +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); + + static std::string StaticAlgorithmName() { return std::string("HMAC_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); } + + /// \brief Construct a HMAC DRBG + /// \param entropy the entropy to instantiate the generator + /// \param entropyLength the size of the entropy buffer + /// \param nonce additional input to instantiate the generator + /// \param nonceLength the size of the nonce buffer + /// \param personalization additional input to instantiate the generator + /// \param personalizationLength the size of the personalization buffer + /// \throw NIST_DRBG::Err if the generator is instantiated with insufficient entropy + /// \details All NIST DRBGs must be instaniated with at least MINIMUM_ENTROPY bytes of entropy. + /// The byte array for entropy must meet NIST + /// SP 800-90B or SP 800-90C requirements. + /// \details The nonce and personalization are optional byte arrays. If nonce is supplied, + /// then it should be at least MINIMUM_NONCE bytes of entropy. + /// \details An example of instantiating a SHA256 generator is shown below. + /// The example provides more entropy than required for SHA256. The NonblockingRng meets the + /// requirements of NIST SP 800-90B or SP 800-90C. + /// RDRAND() and RDSEED() generators would work as well. + ///
+    ///   SecByteBlock entropy(48), result(128);
+    ///   NonblockingRng prng;
+    ///   RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
+    ///
+    ///   HMAC_DRBG drbg(entropy, 32, entropy+32, 16);
+    ///   drbg.GenerateBlock(result, result.size());
+    /// 
+ 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); + } + + unsigned int SecurityStrength() const {return SECURITY_STRENGTH;} + unsigned int SeedLength() const {return SEED_LENGTH;} + unsigned int MinEntropyLength() const {return MINIMUM_ENTROPY;} + unsigned int MaxEntropyLength() const {return MAXIMUM_ENTROPY;} + unsigned int MinNonceLength() const {return MINIMUM_NONCE;} + unsigned int MaxNonceLength() const {return MAXIMUM_NONCE;} + unsigned int MaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;} + unsigned int MaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;} + + void IncorporateEntropy(const byte *input, size_t length) + {return DRBG_Reseed(input, length, NULLPTR, 0);} + + void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength) + {return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);} + + void GenerateBlock(byte *output, size_t size) + {return HMAC_Generate(NULLPTR, 0, output, size);} + + 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, + const byte* personalization, size_t personalizationLength); + + // 10.1.2.4 Reseeding a HMAC_DRBG Instantiation (p.46) + void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength); + + // 10.1.2.5 Generating Pseudorandom Bits Using HMAC_DRBG (p.46) + void HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size); + + // 10.1.2.2 Derivation Function Using a HMAC Function (HMAC_Update) (p.44) + void HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3); + +private: + HMAC m_hmac; + SecByteBlock m_k, m_v; + word64 m_reseed; +}; + +// typedef HMAC_DRBG HMAC_SHA1_DRBG; +// typedef HMAC_DRBG HMAC_SHA256_DRBG; +// typedef HMAC_DRBG HMAC_SHA384_DRBG; +// typedef HMAC_DRBG HMAC_SHA512_DRBG; + +// ************************************************************* + +// 10.1.1.2 Instantiation of Hash_DRBG (p.39) +template +void Hash_DRBG::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength, + const byte* personalization, size_t personalizationLength) +{ + // SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security + // strength of the instantiation. Additional entropy may be provided in the nonce or the optional + // personalization string during instantiation, or in the additional input during reseeding and generation, + // but this is not required and does not increase the "official" security strength of the DRBG + // instantiation that is recorded in the internal state. + CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY); + if (entropyLength < MINIMUM_ENTROPY) + throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during instantiate"); + + // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce, + // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds. + CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY); + CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE); + CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION); + + const byte zero = 0; + SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH); + Hash_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULLPTR, 0, t1, t1.size()); + Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size()); + + m_v.swap(t1); m_c.swap(t2); + m_reseed = 1; +} + +// 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.40) +template +void Hash_DRBG::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength) +{ + // SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security + // strength of the instantiation. Additional entropy may be provided in the nonce or the optional + // personalization string during instantiation, or in the additional input during reseeding and generation, + // but this is not required and does not increase the "official" security strength of the DRBG + // instantiation that is recorded in the internal state.. + CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY); + if (entropyLength < MINIMUM_ENTROPY) + throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during reseed"); + + // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce, + // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds. + CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY); + CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL); + + const byte zero = 0, one = 1; + SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH); + Hash_Update(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, t1, t1.size()); + Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size()); + + m_v.swap(t1); m_c.swap(t2); + m_reseed = 1; +} + +// 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.41) +template +void Hash_DRBG::Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size) +{ + // Step 1 + if (static_cast(m_reseed) >= static_cast(MaxRequestBeforeReseed())) + throw NIST_DRBG::Err("Hash_DRBG", "Reseed required"); + + if (size > MaxBytesPerRequest()) + throw NIST_DRBG::Err("Hash_DRBG", "Request size exceeds limit"); + + // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce, + // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds. + CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL); + + // Step 2 + if (additional && additionaLength) + { + const byte two = 2; + m_temp.New(HASH::DIGESTSIZE); + + 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] + m_temp[j] + carry; + m_v[i] = static_cast(carry); + i--; j--; carry >>= 8; + } + while (i>=0) + { + carry = m_v[i] + carry; + m_v[i] = static_cast(carry); + i--; carry >>= 8; + } + } + + // Step 3 + { + m_temp.Assign(m_v); + while (size) + { + m_hash.Update(m_temp, m_temp.size()); + size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE); + m_hash.TruncatedFinal(output, count); + + IncrementCounterByOne(m_temp, static_cast(m_temp.size())); + size -= count; output += count; + } + } + + // Steps 4-7 + { + const byte three = 3; + m_temp.New(HASH::DIGESTSIZE); + + 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; + + while (k>=0) + { + carry = m_v[i] + m_c[i] + m_temp[j] + GetByte(BIG_ENDIAN_ORDER, m_reseed, k) + carry; + m_v[i] = static_cast(carry); + i--; j--; k--; carry >>= 8; + } + + while (j>=0) + { + carry = m_v[i] + m_c[i] + m_temp[j] + carry; + m_v[i] = static_cast(carry); + i--; j--; carry >>= 8; + } + + while (i>=0) + { + carry = m_v[i] + m_c[i] + carry; + m_v[i] = static_cast(carry); + i--; carry >>= 8; + } + } + + m_reseed++; +} + +// 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.49) +template +void Hash_DRBG::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) +{ + byte counter = 1; + word32 bits = ConditionalByteReverse(BIG_ENDIAN_ORDER, static_cast(outlen*8)); + + while (outlen) + { + m_hash.Update(&counter, 1); + m_hash.Update(reinterpret_cast(&bits), 4); + + if (input1 && inlen1) + m_hash.Update(input1, inlen1); + if (input2 && inlen2) + m_hash.Update(input2, inlen2); + if (input3 && inlen3) + m_hash.Update(input3, inlen3); + if (input4 && inlen4) + m_hash.Update(input4, inlen4); + + size_t count = STDMIN(outlen, (size_t)HASH::DIGESTSIZE); + m_hash.TruncatedFinal(output, count); + + output += count; outlen -= count; + counter++; + } +} + +// ************************************************************* + +// 10.1.2.3 Instantiation of HMAC_DRBG (p.45) +template +void HMAC_DRBG::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength, + const byte* personalization, size_t personalizationLength) +{ + // SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security + // strength of the instantiation. Additional entropy may be provided in the nonce or the optional + // personalization string during instantiation, or in the additional input during reseeding and generation, + // but this is not required and does not increase the "official" security strength of the DRBG + // instantiation that is recorded in the internal state. + CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY); + if (entropyLength < MINIMUM_ENTROPY) + throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during instantiate"); + + // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce, + // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds. + CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY); + CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE); + CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION); + + std::fill(m_k.begin(), m_k.begin()+m_k.size(), byte(0)); + std::fill(m_v.begin(), m_v.begin()+m_v.size(), byte(1)); + + HMAC_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength); + m_reseed = 1; +} + +// 10.1.2.4 Reseeding a HMAC_DRBG Instantiation (p.46) +template +void HMAC_DRBG::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength) +{ + // SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security + // strength of the instantiation. Additional entropy may be provided in the nonce or the optional + // personalization string during instantiation, or in the additional input during reseeding and generation, + // but this is not required and does not increase the "official" security strength of the DRBG + // instantiation that is recorded in the internal state.. + CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY); + if (entropyLength < MINIMUM_ENTROPY) + throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during reseed"); + + // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce, + // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds. + CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY); + CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL); + + HMAC_Update(entropy, entropyLength, additional, additionaLength, NULLPTR, 0); + m_reseed = 1; +} + +// 10.1.2.5 Generating Pseudorandom Bits Using HMAC_DRBG (p.46) +template +void HMAC_DRBG::HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size) +{ + // Step 1 + if (static_cast(m_reseed) >= static_cast(MaxRequestBeforeReseed())) + throw NIST_DRBG::Err("HMAC_DRBG", "Reseed required"); + + if (size > MaxBytesPerRequest()) + throw NIST_DRBG::Err("HMAC_DRBG", "Request size exceeds limit"); + + // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce, + // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds. + CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL); + + // Step 2 + if (additional && additionaLength) + HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0); + + // Step 3 + m_hmac.SetKey(m_k, m_k.size()); + + while (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); + std::memcpy(output, m_v, count); + size -= count; output += count; + } + + HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0); + m_reseed++; +} + +// 10.1.2.2 Derivation Function Using a HMAC Function (HMAC_Update) (p.44) +template +void HMAC_DRBG::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; + + // Step 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) + m_hmac.Update(input1, inlen1); + if (input2 && inlen2) + m_hmac.Update(input2, inlen2); + if (input3 && inlen3) + m_hmac.Update(input3, inlen3); + + m_hmac.TruncatedFinal(m_k, m_k.size()); + + // Step 2 + m_hmac.SetKey(m_k, m_k.size()); + m_hmac.Update(m_v, m_v.size()); + + m_hmac.TruncatedFinal(m_v, m_v.size()); + + // Step 3 + if ((inlen1 | inlen2 | inlen3) == 0) + return; + + // Step 4 + m_hmac.SetKey(m_k, m_k.size()); + m_hmac.Update(m_v, m_v.size()); + m_hmac.Update(&one, 1); + + if (input1 && inlen1) + m_hmac.Update(input1, inlen1); + if (input2 && inlen2) + m_hmac.Update(input2, inlen2); + if (input3 && inlen3) + m_hmac.Update(input3, inlen3); + + m_hmac.TruncatedFinal(m_k, m_k.size()); + + // Step 5 + m_hmac.SetKey(m_k, m_k.size()); + m_hmac.Update(m_v, m_v.size()); + + m_hmac.TruncatedFinal(m_v, m_v.size()); +} + +NAMESPACE_END + +#endif // CRYPTOPP_NIST_DRBG_H diff --git a/third_party/cryptoppwin/include/cryptopp/dsa.h b/third_party/cryptoppwin/include/cryptopp/dsa.h new file mode 100644 index 00000000..f49ed92b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/dsa.h @@ -0,0 +1,53 @@ +// dsa.h - originally written and placed in the public domain by Wei Dai + +/// \file dsa.h +/// \brief Classes for the DSA signature algorithm + +#ifndef CRYPTOPP_DSA_H +#define CRYPTOPP_DSA_H + +#include "cryptlib.h" +#include "gfpcrypt.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief DSA Signature Format +/// \details The DSA signature format used by Crypto++ is as defined by IEEE P1363. +/// OpenSSL, Java and .Net use the DER format, and OpenPGP uses the OpenPGP format. +/// \sa DSAConvertSignatureFormat +/// on the Crypto++ wiki. +/// \since Crypto++ 1.0 +enum DSASignatureFormat { + /// \brief Crypto++ native signature encoding format + DSA_P1363, + /// \brief signature encoding format used by OpenSSL, Java and .Net + DSA_DER, + /// \brief OpenPGP signature encoding format + DSA_OPENPGP +}; + +/// \brief Converts between signature encoding formats +/// \param buffer byte buffer for the converted signature encoding +/// \param bufferSize the length of the converted signature encoding buffer +/// \param toFormat the source signature format +/// \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 toFormat == DSA_P1363, then +/// bufferSize must equal publicKey.SignatureLength() or +/// verifier.SignatureLength(). +/// \details If the destination buffer is too small then the output of the +/// encoded r and s will be truncated. Be sure to provide +/// an adequately sized buffer and check the return value for the number of +/// bytes written. +/// \sa DSAConvertSignatureFormat +/// 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 // CRYPTOPP_DSA_H diff --git a/third_party/cryptoppwin/include/cryptopp/eax.h b/third_party/cryptoppwin/include/cryptopp/eax.h new file mode 100644 index 00000000..6dc1fa6d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/eax.h @@ -0,0 +1,112 @@ +// eax.h - originally written and placed in the public domain by Wei Dai + +/// \file eax.h +/// \brief EAX block cipher mode of operation + +#ifndef CRYPTOPP_EAX_H +#define CRYPTOPP_EAX_H + +#include "authenc.h" +#include "modes.h" +#include "cmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief EAX block cipher base implementation +/// \details Base implementation of the AuthenticatedSymmetricCipher interface +/// \since Crypto++ 5.6.0 +class CRYPTOPP_NO_VTABLE EAX_Base : public AuthenticatedSymmetricCipherBase +{ +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 + {return GetMAC().MaxKeyLength();} + size_t DefaultKeyLength() const + {return GetMAC().DefaultKeyLength();} + size_t GetValidKeyLength(size_t n) const + {return GetMAC().GetValidKeyLength(n);} + bool IsValidKeyLength(size_t n) const + {return GetMAC().IsValidKeyLength(n);} + unsigned int OptimalDataAlignment() const + {return GetMAC().OptimalDataAlignment();} + IV_Requirement IVRequirement() const + {return UNIQUE_IV;} + unsigned int IVSize() const + {return GetMAC().TagSize();} + unsigned int MinIVLength() const + {return 0;} + unsigned int MaxIVLength() const + {return UINT_MAX;} + unsigned int DigestSize() const + {return GetMAC().TagSize();} + lword MaxHeaderLength() const + {return LWORD_MAX;} + lword MaxMessageLength() const + {return LWORD_MAX;} + +protected: + // AuthenticatedSymmetricCipherBase + bool AuthenticationIsOnPlaintext() const + {return false;} + unsigned int AuthenticationBlockSize() const + {return 1;} + void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + void Resync(const byte *iv, size_t len); + size_t AuthenticateBlocks(const byte *data, size_t len); + void AuthenticateLastHeaderBlock(); + void AuthenticateLastFooterBlock(byte *mac, size_t macSize); + SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} + const CMAC_Base & GetMAC() const {return const_cast(this)->AccessMAC();} + virtual CMAC_Base & AccessMAC() =0; + + CTR_Mode_ExternalCipher::Encryption m_ctr; +}; + +/// \brief EAX block cipher final implementation +/// \tparam T_BlockCipher block cipher +/// \tparam T_IsEncryption direction in which to operate the cipher +/// \since Crypto++ 5.6.0 +template +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;} + +private: + CMAC_Base & AccessMAC() {return m_cmac;} + CMAC m_cmac; +}; + +#ifdef EAX // EAX is defined to 11 on GCC 3.4.3, OpenSolaris 8.11 +#undef EAX +#endif + +/// \brief EAX block cipher mode of operation +/// \tparam T_BlockCipher block cipher +/// \details \p EAX provides the \p Encryption and \p Decryption typedef. See EAX_Base +/// and EAX_Final for the AuthenticatedSymmetricCipher implementation. +/// \sa EAX Mode and +/// Modes of Operation +/// on the Crypto++ wiki. +/// \since Crypto++ 5.6.0 +template +struct EAX : public AuthenticatedSymmetricCipherDocumentation +{ + typedef EAX_Final Encryption; + typedef EAX_Final Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ec2n.h b/third_party/cryptoppwin/include/cryptopp/ec2n.h new file mode 100644 index 00000000..529da045 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ec2n.h @@ -0,0 +1,136 @@ +// ec2n.h - originally written and placed in the public domain by Wei Dai + +/// \file ec2n.h +/// \brief Classes for Elliptic Curves over binary fields + +#ifndef CRYPTOPP_EC2N_H +#define CRYPTOPP_EC2N_H + +#include "cryptlib.h" +#include "gf2n.h" +#include "integer.h" +#include "algebra.h" +#include "ecpoint.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Elliptic Curve over GF(2^n) +class CRYPTOPP_DLL EC2N : public AbstractGroup, public EncodedPoint +{ +public: + typedef GF2NP Field; + typedef Field::Element FieldElement; + typedef EC2NPoint Point; + + virtual ~EC2N() {} + + /// \brief Construct an EC2N + EC2N() {} + + /// \brief Construct an EC2N + /// \param field Field, GF2NP derived class + /// \param a Field::Element + /// \param b Field::Element + EC2N(const Field &field, const Field::Element &a, const Field::Element &b) + : m_field(field), m_a(a), m_b(b) {} + + /// \brief Construct an EC2N from BER encoded parameters + /// \param bt BufferedTransformation derived object + /// \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 + /// \param bt BufferedTransformation derived object + void DEREncode(BufferedTransformation &bt) const; + + 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;} + const Point& Add(const Point &P, const Point &Q) const; + const Point& Double(const Point &P) const; + + Point Multiply(const Integer &k, const Point &P) const + {return ScalarMultiply(P, k);} + Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const + {return CascadeScalarMultiply(P, k1, Q, k2);} + + bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const; + bool VerifyPoint(const Point &P) const; + + unsigned int EncodedPointSize(bool compressed = false) const + {return 1 + (compressed?1:2)*m_field->MaxElementByteLength();} + // returns false if point is compressed and not valid (doesn't check if uncompressed) + bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; + bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; + void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; + void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Point BERDecodePoint(BufferedTransformation &bt) const; + void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Integer FieldSize() const {return Integer::Power2(m_field->MaxElementBitLength());} + const Field & GetField() const {return *m_field;} + const FieldElement & GetA() const {return m_a;} + const FieldElement & GetB() const {return m_b;} + + bool operator==(const EC2N &rhs) const + {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;} + +private: + clonable_ptr m_field; + FieldElement m_a, m_b; + mutable Point m_R; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; + +/// \brief Elliptic Curve precomputation +/// \tparam EC elliptic curve field +template class EcPrecomputation; + +/// \brief EC2N precomputation specialization +/// \details Implementation of DL_GroupPrecomputation +/// \sa DL_GroupPrecomputation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +public: + typedef EC2N EllipticCurve; + + virtual ~EcPrecomputation() {} + + // DL_GroupPrecomputation + const AbstractGroup & GetGroup() const {return m_ec;} + Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec.BERDecodePoint(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec.DEREncodePoint(bt, v, false);} + + /// \brief Set the elliptic curve + /// \param ec ECP derived class + /// \details SetCurve() is not inherited + void SetCurve(const EC2N &ec) {m_ec = ec;} + + /// \brief Get the elliptic curve + /// \return EC2N curve + /// \details GetCurve() is not inherited + const EC2N & GetCurve() const {return m_ec;} + +private: + EC2N m_ec; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/eccrypto.h b/third_party/cryptoppwin/include/cryptopp/eccrypto.h new file mode 100644 index 00000000..17ccb134 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/eccrypto.h @@ -0,0 +1,686 @@ +// eccrypto.h - originally written and placed in the public domain by Wei Dai +// deterministic signatures added by by Douglas Roark + +/// \file eccrypto.h +/// \brief Classes and functions for Elliptic Curves over prime and binary fields + +#ifndef CRYPTOPP_ECCRYPTO_H +#define CRYPTOPP_ECCRYPTO_H + +#include "config.h" +#include "cryptlib.h" +#include "pubkey.h" +#include "integer.h" +#include "asn.h" +#include "hmac.h" +#include "sha.h" +#include "gfpcrypt.h" +#include "dh.h" +#include "mqv.h" +#include "hmqv.h" +#include "fhmqv.h" +#include "ecp.h" +#include "ec2n.h" + +#include + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +#endif + +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. +template +class DL_GroupParameters_EC : public DL_GroupParametersImpl > +{ + typedef DL_GroupParameters_EC ThisClass; + +public: + typedef EC EllipticCurve; + typedef typename EllipticCurve::Point Point; + typedef Point Element; + typedef IncompatibleCofactorMultiplication DefaultCofactorOption; + + virtual ~DL_GroupParameters_EC() {} + + /// \brief Construct an EC GroupParameters + DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(true) {} + + /// \brief Construct an EC GroupParameters + /// \param oid the OID of a curve + DL_GroupParameters_EC(const OID &oid) + : m_compress(false), m_encodeAsOID(true) {Initialize(oid);} + + /// \brief Construct an EC GroupParameters + /// \param ec the elliptic curve + /// \param G the base point + /// \param n the order of the base point + /// \param k the cofactor + DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) + : m_compress(false), m_encodeAsOID(true) {Initialize(ec, G, n, k);} + + /// \brief Construct an EC GroupParameters + /// \param bt BufferedTransformation with group parameters + DL_GroupParameters_EC(BufferedTransformation &bt) + : m_compress(false), m_encodeAsOID(true) {BERDecode(bt);} + + /// \brief Initialize an EC GroupParameters using {EC,G,n,k} + /// \param ec the elliptic curve + /// \param G the base point + /// \param n the order of the base point + /// \param k the cofactor + /// \details This Initialize() function overload initializes group parameters from existing parameters. + void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) + { + this->m_groupPrecomputation.SetCurve(ec); + this->SetSubgroupGenerator(G); + m_n = n; + m_k = k; + } + + /// \brief Initialize a DL_GroupParameters_EC {EC,G,n,k} + /// \param oid the OID of a curve + /// \details This Initialize() function overload initializes group parameters from existing parameters. + void Initialize(const OID &oid); + + // NameValuePairs + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // GeneratibleCryptoMaterial interface + /// this implementation doesn't actually generate a curve, it just initializes the parameters with existing values + /*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + // DL_GroupParameters + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;} + DL_FixedBasePrecomputation & AccessBasePrecomputation() {return this->m_gpc;} + const Integer & GetSubgroupOrder() const {return m_n;} + Integer GetCofactor() const; + bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; + bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation *precomp) const; + bool FastSubgroupCheckAvailable() const {return false;} + void EncodeElement(bool reversible, const Element &element, byte *encoded) const + { + if (reversible) + GetCurve().EncodePoint(encoded, element, m_compress); + else + element.x.Encode(encoded, GetEncodedElementSize(false)); + } + virtual unsigned int GetEncodedElementSize(bool reversible) const + { + if (reversible) + return GetCurve().EncodedPointSize(m_compress); + else + return GetCurve().GetField().MaxElementByteLength(); + } + Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const + { + Point result; + if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true))) + throw DL_BadElement(); + if (checkForGroupMembership && !ValidateElement(1, result, NULLPTR)) + throw DL_BadElement(); + return result; + } + Integer ConvertElementToInteger(const Element &element) const; + Integer GetMaxExponent() const {return GetSubgroupOrder()-1;} + bool IsIdentity(const Element &element) const {return element.identity;} + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";} + + // ASN1Key + OID GetAlgorithmID() const; + + // used by MQV + Element MultiplyElements(const Element &a, const Element &b) const; + Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const; + + // non-inherited + + // enumerate OIDs for recommended parameters, use OID() to get first one + static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid); + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + void SetPointCompression(bool compress) {m_compress = compress;} + bool GetPointCompression() const {return m_compress;} + + void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;} + bool GetEncodeAsOID() const {return m_encodeAsOID;} + + const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();} + + bool operator==(const ThisClass &rhs) const + {return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);} + +protected: + unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();} + unsigned int ExponentLength() const {return m_n.ByteCount();} + + OID m_oid; // set if parameters loaded from a recommended curve + Integer m_n; // order of base point + mutable Integer m_k; // cofactor + mutable bool m_compress, m_encodeAsOID; // presentation details +}; + +inline std::ostream& operator<<(std::ostream& os, const DL_GroupParameters_EC::Element& obj); + +/// \brief Elliptic Curve Discrete Log (DL) public key +/// \tparam EC elliptic curve field +template +class DL_PublicKey_EC : public DL_PublicKeyImpl > +{ +public: + typedef typename EC::Point Element; + + virtual ~DL_PublicKey_EC() {} + + /// \brief Initialize an EC Public Key using {GP,Q} + /// \param params group parameters + /// \param Q the public point + /// \details This Initialize() function overload initializes a public key from existing parameters. + void Initialize(const DL_GroupParameters_EC ¶ms, const Element &Q) + {this->AccessGroupParameters() = params; this->SetPublicElement(Q);} + + /// \brief Initialize an EC Public Key using {EC,G,n,Q} + /// \param ec the elliptic curve + /// \param G the base point + /// \param n the order of the base point + /// \param Q the public point + /// \details This Initialize() function overload initializes a public key from existing parameters. + void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q) + {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);} + + // X509PublicKey + void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePublicKey(BufferedTransformation &bt) const; +}; + +/// \brief Elliptic Curve Discrete Log (DL) private key +/// \tparam EC elliptic curve field +template +class DL_PrivateKey_EC : public DL_PrivateKeyImpl > +{ +public: + typedef typename EC::Point Element; + + virtual ~DL_PrivateKey_EC(); + + /// \brief Initialize an EC Private Key using {GP,x} + /// \param params group parameters + /// \param x the private exponent + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const DL_GroupParameters_EC ¶ms, const Integer &x) + {this->AccessGroupParameters() = params; this->SetPrivateExponent(x);} + + /// \brief Initialize an EC Private Key using {EC,G,n,x} + /// \param ec the elliptic curve + /// \param G the base point + /// \param n the order of the base point + /// \param x the private exponent + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x) + {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);} + + /// \brief Create an EC private key + /// \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. + void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC ¶ms) + {this->GenerateRandom(rng, params);} + + /// \brief Create an EC private key + /// \param rng a RandomNumberGenerator derived class + /// \param ec the elliptic curve + /// \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. + void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n) + {this->GenerateRandom(rng, DL_GroupParameters_EC(ec, G, n));} + + // PKCS8PrivateKey + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; +}; + +// Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499 +template +DL_PrivateKey_EC::~DL_PrivateKey_EC() {} + +/// \brief Elliptic Curve Diffie-Hellman +/// \tparam EC elliptic curve field +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \sa CofactorMultiplicationOption, Elliptic Curve Diffie-Hellman, AKA ECDH +/// \since Crypto++ 3.0 +template ::DefaultCofactorOption> +struct ECDH +{ + typedef DH_Domain, COFACTOR_OPTION> Domain; +}; + +/// \brief Elliptic Curve Menezes-Qu-Vanstone +/// \tparam EC elliptic curve field +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \sa CofactorMultiplicationOption, Elliptic Curve Menezes-Qu-Vanstone, AKA ECMQV +template ::DefaultCofactorOption> +struct ECMQV +{ + typedef MQV_Domain, COFACTOR_OPTION> Domain; +}; + +/// \brief Hashed Elliptic Curve Menezes-Qu-Vanstone +/// \tparam EC elliptic curve field +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance +/// Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided. +/// \sa CofactorMultiplicationOption +template ::DefaultCofactorOption, class HASH = SHA256> +struct ECHMQV +{ + typedef HMQV_Domain, COFACTOR_OPTION, HASH> Domain; +}; + +typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA1 >::Domain ECHMQV160; +typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA256 >::Domain ECHMQV256; +typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA384 >::Domain ECHMQV384; +typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512 >::Domain ECHMQV512; + +/// \brief Fully Hashed Elliptic Curve Menezes-Qu-Vanstone +/// \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 Secure and Efficient Authenticated Diffie-Hellman Protocol. +/// Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. +/// \sa CofactorMultiplicationOption +template ::DefaultCofactorOption, class HASH = SHA256> +struct ECFHMQV +{ + typedef FHMQV_Domain, COFACTOR_OPTION, HASH> Domain; +}; + +typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA1 >::Domain ECFHMQV160; +typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA256 >::Domain ECFHMQV256; +typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA384 >::Domain ECFHMQV384; +typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512 >::Domain ECFHMQV512; + +/// \brief Elliptic Curve Discrete Log (DL) keys +/// \tparam EC elliptic curve field +template +struct DL_Keys_EC +{ + typedef DL_PublicKey_EC PublicKey; + typedef DL_PrivateKey_EC PrivateKey; +}; + +// Forward declaration; documented below +template +struct ECDSA; + +/// \brief Elliptic Curve DSA keys +/// \tparam EC elliptic curve field +/// \since Crypto++ 3.2 +template +struct DL_Keys_ECDSA +{ + typedef DL_PublicKey_EC PublicKey; + typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA > PrivateKey; +}; + +/// \brief Elliptic Curve DSA (ECDSA) signature algorithm +/// \tparam EC elliptic curve field +/// \since Crypto++ 3.2 +template +class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";} +}; + +/// \brief Elliptic Curve DSA (ECDSA) signature algorithm based on RFC 6979 +/// \tparam EC elliptic curve field +/// \sa RFC 6979, Deterministic Usage of the +/// Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) +/// \since Crypto++ 6.0 +template +class DL_Algorithm_ECDSA_RFC6979 : public DL_Algorithm_DSA_RFC6979 +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECDSA-RFC6979";} +}; + +/// \brief Elliptic Curve NR (ECNR) signature algorithm +/// \tparam EC elliptic curve field +template +class DL_Algorithm_ECNR : public DL_Algorithm_NR +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECNR";} +}; + +/// \brief Elliptic Curve DSA (ECDSA) signature scheme +/// \tparam EC elliptic curve field +/// \tparam H HashTransformation derived class +/// \sa ECDSA +/// \since Crypto++ 3.2 +template +struct ECDSA : public DL_SS, DL_Algorithm_ECDSA, DL_SignatureMessageEncodingMethod_DSA, H> +{ +}; + +/// \brief Elliptic Curve DSA (ECDSA) deterministic signature scheme +/// \tparam EC elliptic curve field +/// \tparam H HashTransformation derived class +/// \sa Deterministic Usage of the +/// Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) +/// \since Crypto++ 6.0 +template +struct ECDSA_RFC6979 : public DL_SS< + DL_Keys_ECDSA, + DL_Algorithm_ECDSA_RFC6979, + DL_SignatureMessageEncodingMethod_DSA, + H, + ECDSA_RFC6979 > +{ + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("ECDSA-RFC6979/") + H::StaticAlgorithmName();} +}; + +/// \brief Elliptic Curve NR (ECNR) signature scheme +/// \tparam EC elliptic curve field +/// \tparam H HashTransformation derived class +template +struct ECNR : public DL_SS, DL_Algorithm_ECNR, DL_SignatureMessageEncodingMethod_NR, H> +{ +}; + +// ****************************************** + +template +class DL_PublicKey_ECGDSA; +template +class DL_PrivateKey_ECGDSA; + +/// \brief Elliptic Curve German DSA key for ISO/IEC 15946 +/// \tparam EC elliptic curve field +/// \sa ECGDSA +/// \since Crypto++ 6.0 +template +class DL_PrivateKey_ECGDSA : public DL_PrivateKeyImpl > +{ +public: + typedef typename EC::Point Element; + + virtual ~DL_PrivateKey_ECGDSA() {} + + /// \brief Initialize an EC Private Key using {GP,x} + /// \param params group parameters + /// \param x the private exponent + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const DL_GroupParameters_EC ¶ms, const Integer &x) + { + this->AccessGroupParameters() = params; + this->SetPrivateExponent(x); + CRYPTOPP_ASSERT(x>=1 && x<=params.GetSubgroupOrder()-1); + } + + /// \brief Initialize an EC Private Key using {EC,G,n,x} + /// \param ec the elliptic curve + /// \param G the base point + /// \param n the order of the base point + /// \param x the private exponent + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x) + { + this->AccessGroupParameters().Initialize(ec, G, n); + this->SetPrivateExponent(x); + CRYPTOPP_ASSERT(x>=1 && x<=this->AccessGroupParameters().GetSubgroupOrder()-1); + } + + /// \brief Create an EC private key + /// \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. + void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC ¶ms) + {this->GenerateRandom(rng, params);} + + /// \brief Create an EC private key + /// \param rng a RandomNumberGenerator derived class + /// \param ec the elliptic curve + /// \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. + void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n) + {this->GenerateRandom(rng, DL_GroupParameters_EC(ec, G, n));} + + virtual void MakePublicKey(DL_PublicKey_ECGDSA &pub) const + { + const DL_GroupParameters& params = this->GetAbstractGroupParameters(); + pub.AccessAbstractGroupParameters().AssignFrom(params); + const Integer &xInv = this->GetPrivateExponent().InverseMod(params.GetSubgroupOrder()); + pub.SetPublicElement(params.ExponentiateBase(xInv)); + CRYPTOPP_ASSERT(xInv.NotZero()); + } + + virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper, + DL_PrivateKey_ECGDSA >(this, name, valueType, pValue).Assignable(); + } + + virtual void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper, + DL_PrivateKey_ECGDSA >(this, source); + } + + // PKCS8PrivateKey + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; +}; + +/// \brief Elliptic Curve German DSA key for ISO/IEC 15946 +/// \tparam EC elliptic curve field +/// \sa ECGDSA +/// \since Crypto++ 6.0 +template +class DL_PublicKey_ECGDSA : public DL_PublicKeyImpl > +{ + typedef DL_PublicKey_ECGDSA ThisClass; + +public: + typedef typename EC::Point Element; + + virtual ~DL_PublicKey_ECGDSA() {} + + /// \brief Initialize an EC Public Key using {GP,Q} + /// \param params group parameters + /// \param Q the public point + /// \details This Initialize() function overload initializes a public key from existing parameters. + void Initialize(const DL_GroupParameters_EC ¶ms, const Element &Q) + {this->AccessGroupParameters() = params; this->SetPublicElement(Q);} + + /// \brief Initialize an EC Public Key using {EC,G,n,Q} + /// \param ec the elliptic curve + /// \param G the base point + /// \param n the order of the base point + /// \param Q the public point + /// \details This Initialize() function overload initializes a public key from existing parameters. + void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q) + {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);} + + virtual void AssignFrom(const NameValuePairs &source) + { + DL_PrivateKey_ECGDSA *pPrivateKey = NULLPTR; + if (source.GetThisPointer(pPrivateKey)) + pPrivateKey->MakePublicKey(*this); + else + { + this->AccessAbstractGroupParameters().AssignFrom(source); + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement); + } + } + + // DL_PublicKey + virtual void SetPublicElement(const Element &y) + {this->AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);} + + // X509PublicKey + void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePublicKey(BufferedTransformation &bt) const; +}; + +/// \brief Elliptic Curve German DSA keys for ISO/IEC 15946 +/// \tparam EC elliptic curve field +/// \sa ECGDSA +/// \since Crypto++ 6.0 +template +struct DL_Keys_ECGDSA +{ + typedef DL_PublicKey_ECGDSA PublicKey; + typedef DL_PrivateKey_ECGDSA PrivateKey; +}; + +/// \brief Elliptic Curve German DSA signature algorithm +/// \tparam EC elliptic curve field +/// \sa ECGDSA +/// \since Crypto++ 6.0 +template +class DL_Algorithm_ECGDSA : public DL_Algorithm_GDSA_ISO15946 +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECGDSA";} +}; + +/// \brief Elliptic Curve German Digital Signature Algorithm signature scheme +/// \tparam EC elliptic curve field +/// \tparam H HashTransformation derived class +/// \sa Erwin Hess, Marcus Schafheutle, and Pascale Serf The Digital Signature Scheme +/// ECGDSA (October 24, 2006) +/// \since Crypto++ 6.0 +template +struct ECGDSA : public DL_SS< + DL_Keys_ECGDSA, + DL_Algorithm_ECGDSA, + DL_SignatureMessageEncodingMethod_DSA, + H> +{ + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("ECGDSA-ISO15946/") + H::StaticAlgorithmName();} +}; + +// ****************************************** + +/// \brief Elliptic Curve Integrated Encryption Scheme +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \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 u·V, v·U 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 +/// IND-CCA2, 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 NoCofactorMultiplication, DHAES_MODE=true and LABEL_OCTETS=false. +/// \details The default template parameters ensure compatibility with Bouncy Castle 1.54 and Botan 1.11. The combination of +/// IncompatibleCofactorMultiplication and DHAES_MODE=true is recommended for best efficiency and security. +/// SHA1 is used for compatibility reasons, but it can be changed if desired. +/// \sa DLIES, ECIES_P1363, Elliptic Curve Integrated Encryption Scheme (ECIES), +/// Martínez, Encinas, and Ávila's A Survey of the Elliptic +/// Curve Integrated Encryption Schemes +/// \since Crypto++ 4.0, Crypto++ 5.7 for Bouncy Castle and Botan compatibility +template +struct ECIES + : public DL_ES< + DL_Keys_EC, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE, LABEL_OCTETS>, + ECIES > +{ + // TODO: fix this after name is standardized + 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 +/// IND-CCA2, 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 NoCofactorMultiplication, DHAES_MODE=false and LABEL_OCTETS=true. +/// \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 NoCofactorMultiplication, DHAES_MODE=true and LABEL_OCTETS=false. +/// \details The default template parameters ensure compatibility with P1363. The combination of +/// IncompatibleCofactorMultiplication and DHAES_MODE=true is recommended for best efficiency and security. +/// SHA1 is used for compatibility reasons, but it can be changed if desired. +/// \sa DLIES, ECIES, Elliptic Curve Integrated Encryption Scheme (ECIES), +/// Martínez, Encinas, and Ávila's A Survey of the Elliptic +/// Curve Integrated Encryption Schemes +/// \since Crypto++ 4.0 +template +struct ECIES_P1363 + : public DL_ES< + DL_Keys_EC, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, false, true>, + ECIES > +{ + // 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 +#include "eccrypto.cpp" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_ECGDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_ECGDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_ECGDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_ECGDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ecp.h b/third_party/cryptoppwin/include/cryptopp/ecp.h new file mode 100644 index 00000000..28929d00 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ecp.h @@ -0,0 +1,167 @@ +// ecp.h - originally written and placed in the public domain by Wei Dai + +/// \file ecp.h +/// \brief Classes for Elliptic Curves over prime fields + +#ifndef CRYPTOPP_ECP_H +#define CRYPTOPP_ECP_H + +#include "cryptlib.h" +#include "integer.h" +#include "algebra.h" +#include "modarith.h" +#include "ecpoint.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Elliptic Curve over GF(p), where p is prime +class CRYPTOPP_DLL ECP : public AbstractGroup, public EncodedPoint +{ +public: + typedef ModularArithmetic Field; + typedef Integer FieldElement; + typedef ECPPoint Point; + + virtual ~ECP() {} + + /// \brief Construct an ECP + ECP() {} + + /// \brief Construct an ECP + /// \param ecp the other ECP object + /// \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); + + /// \brief Construct an ECP + /// \param modulus the prime modulus + /// \param a Field::Element + /// \param b Field::Element + ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b) + : m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {} + + /// \brief Construct an ECP from BER encoded parameters + /// \param bt BufferedTransformation derived object + /// \details This constructor will decode and extract the fields + /// fieldID and curve of the sequence ECParameters + ECP(BufferedTransformation &bt); + + /// \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;} + const Point& Add(const Point &P, const Point &Q) const; + const Point& Double(const Point &P) const; + Point ScalarMultiply(const Point &P, const Integer &k) const; + Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const; + void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const; + + Point Multiply(const Integer &k, const Point &P) const + {return ScalarMultiply(P, k);} + Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const + {return CascadeScalarMultiply(P, k1, Q, k2);} + + bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const; + bool VerifyPoint(const Point &P) const; + + unsigned int EncodedPointSize(bool compressed = false) const + {return 1 + (compressed?1:2)*GetField().MaxElementByteLength();} + // returns false if point is compressed and not valid (doesn't check if uncompressed) + bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; + bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; + void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; + void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Point BERDecodePoint(BufferedTransformation &bt) const; + void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Integer FieldSize() const {return GetField().GetModulus();} + const Field & GetField() const {return *m_fieldPtr;} + const FieldElement & GetA() const {return m_a;} + const FieldElement & GetB() const {return m_b;} + + bool operator==(const ECP &rhs) const + {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;} + +private: + clonable_ptr m_fieldPtr; + FieldElement m_a, m_b; + mutable Point m_R; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; + +/// \brief Elliptic Curve precomputation +/// \tparam EC elliptic curve field +template class EcPrecomputation; + +/// \brief ECP precomputation specialization +/// \details Implementation of DL_GroupPrecomputation with input and output +/// conversions for Montgomery modular multiplication. +/// \sa DL_GroupPrecomputation, ModularArithmetic, MontgomeryRepresentation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +public: + typedef ECP EllipticCurve; + + virtual ~EcPrecomputation() {} + + // DL_GroupPrecomputation + bool NeedConversions() const {return true;} + Element ConvertIn(const Element &P) const + {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));}; + Element ConvertOut(const Element &P) const + {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));} + const AbstractGroup & GetGroup() const {return *m_ec;} + Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);} + + /// \brief Set the elliptic curve + /// \param ec ECP derived class + /// \details SetCurve() is not inherited + void SetCurve(const ECP &ec) + { + m_ec.reset(new ECP(ec, true)); + m_ecOriginal = ec; + } + + /// \brief Get the elliptic curve + /// \return ECP curve + /// \details GetCurve() is not inherited + const ECP & GetCurve() const {return *m_ecOriginal;} + +private: + value_ptr m_ec, m_ecOriginal; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ecpoint.h b/third_party/cryptoppwin/include/cryptopp/ecpoint.h new file mode 100644 index 00000000..2be93bc7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ecpoint.h @@ -0,0 +1,146 @@ +// ecpoint.h - written and placed in the public domain by Jeffrey Walton +// Data structures moved from ecp.h and ec2n.h. Added EncodedPoint interface + +/// \file ecpoint.h +/// \brief Classes for Elliptic Curve points +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_ECPOINT_H +#define CRYPTOPP_ECPOINT_H + +#include "cryptlib.h" +#include "integer.h" +#include "algebra.h" +#include "gf2n.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Elliptical Curve Point over GF(p), where p is prime +/// \since Crypto++ 2.0 +struct CRYPTOPP_DLL ECPPoint +{ + virtual ~ECPPoint() {} + + /// \brief Construct an ECPPoint + /// \details identity is set to true + ECPPoint() : identity(true) {} + + /// \brief Construct an ECPPoint from coordinates + /// \details identity is set to false + ECPPoint(const Integer &x, const Integer &y) + : x(x), y(y), identity(false) {} + + /// \brief Tests points for equality + /// \param t the other point + /// \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 + /// \return true if this point is less than other, false otherwise + bool operator< (const ECPPoint &t) const + {return identity ? !t.identity : (!t.identity && (x; + +/// \brief Elliptical Curve Point over GF(2^n) +/// \since Crypto++ 2.0 +struct CRYPTOPP_DLL EC2NPoint +{ + virtual ~EC2NPoint() {} + + /// \brief Construct an EC2NPoint + /// \details identity is set to true + EC2NPoint() : identity(true) {} + + /// \brief Construct an EC2NPoint from coordinates + /// \details identity is set to false + EC2NPoint(const PolynomialMod2 &x, const PolynomialMod2 &y) + : x(x), y(y), identity(false) {} + + /// \brief Tests points for equality + /// \param t the other point + /// \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 + /// \return true if this point is less than other, false otherwise + bool operator< (const EC2NPoint &t) const + {return identity ? !t.identity : (!t.identity && (x; + +/// \brief Abstract class for encoding and decoding ellicptic curve points +/// \tparam Point ellicptic curve point +/// \details EncodedPoint is an interface for encoding and decoding elliptic curve points. +/// The template parameter Point should be a class like ECP or EC2N. +/// \since Crypto++ 6.0 +template +class EncodedPoint +{ +public: + virtual ~EncodedPoint() {} + + /// \brief Decodes an elliptic curve point + /// \param P point which is decoded + /// \param bt source BufferedTransformation + /// \param len number of bytes to read from the BufferedTransformation + /// \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 + /// \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 + /// \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 + /// \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 + /// \param P point which is decoded + /// \param encodedPoint byte array for the encoded point + /// \param compressed flag indicating if the point is compressed + /// \details encodedPoint must be at least EncodedPointSize() in length + virtual void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const =0; + + /// \brief Encodes an elliptic curve point + /// \param bt target BufferedTransformation + /// \param P point which is encoded + /// \param compressed flag indicating if the point is compressed + virtual void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const =0; + + /// \brief BER Decodes an elliptic curve point + /// \param bt source BufferedTransformation + /// \return the decoded elliptic curve point + virtual Point BERDecodePoint(BufferedTransformation &bt) const =0; + + /// \brief DER Encodes an elliptic curve point + /// \param bt target BufferedTransformation + /// \param P point which is encoded + /// \param compressed flag indicating if the point is compressed + virtual void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const =0; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_ECPOINT_H diff --git a/third_party/cryptoppwin/include/cryptopp/elgamal.h b/third_party/cryptoppwin/include/cryptopp/elgamal.h new file mode 100644 index 00000000..f979f0a8 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/elgamal.h @@ -0,0 +1,308 @@ +// elgamal.h - originally written and placed in the public domain by Wei Dai + +/// \file elgamal.h +/// \brief Classes and functions for ElGamal key agreement and encryption schemes + +#ifndef CRYPTOPP_ELGAMAL_H +#define CRYPTOPP_ELGAMAL_H + +#include "cryptlib.h" +#include "modexppc.h" +#include "integer.h" +#include "gfpcrypt.h" +#include "pubkey.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, + public DL_KeyDerivationAlgorithm, + public DL_SymmetricEncryptionAlgorithm +{ +public: + virtual ~ElGamalBase() {} + + void Derive(const DL_GroupParameters &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); + agreedElement.Encode(derivedKey, derivedLength); + } + + size_t GetSymmetricKeyLength(size_t plainTextLength) const + { + CRYPTOPP_UNUSED(plainTextLength); + return GetGroupParameters().GetModulus().ByteCount(); + } + + size_t GetSymmetricCiphertextLength(size_t plainTextLength) const + { + unsigned int len = GetGroupParameters().GetModulus().ByteCount(); + if (plainTextLength <= GetMaxSymmetricPlaintextLength(len)) + return len; + else + return 0; + } + + 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 + return 0; + } + + void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs ¶meters) const + { + CRYPTOPP_UNUSED(parameters); + const Integer &p = GetGroupParameters().GetModulus(); + unsigned int modulusLen = p.ByteCount(); + + SecByteBlock block(modulusLen-1); + rng.GenerateBlock(block, modulusLen-2-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); + } + + DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs ¶meters) const + { + CRYPTOPP_UNUSED(parameters); + const Integer &p = GetGroupParameters().GetModulus(); + unsigned int modulusLen = p.ByteCount(); + + if (cipherTextLength != modulusLen) + return DecodingResult(); + + Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p); + + m.Encode(plainText, 1); + unsigned int plainTextLength = plainText[0]; + if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen)) + return DecodingResult(); + m >>= 8; + m.Encode(plainText, plainTextLength); + return DecodingResult(plainTextLength); + } + + virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0; +}; + +/// \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 ElGamalObjectImpl : + public DL_ObjectImplBase, + public ElGamalBase +{ +public: + virtual ~ElGamalObjectImpl() {} + + size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());} + size_t FixedCiphertextLength() const {return this->CiphertextLength(0);} + + const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();} + + DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const + {return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);} + +protected: + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const {return *this;} + const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const {return *this;} + 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 Load an ElGamal key with the wrong OID then +/// see ElGamal on +/// the Crypto++ wiki. +/// \sa Issue 876, +/// Issue 567 +/// \since Crypto++ 8.3 +template +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 Load an ElGamal key with the wrong OID then + /// see ElGamal on + /// the Crypto++ wiki. + /// \sa Issue 876, + /// Issue 567 + 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 Load an ElGamal key with the wrong OID then +/// see ElGamal on +/// the Crypto++ wiki. +/// \sa Issue 876, +/// Issue 567 +/// \since Crypto++ 8.3 +template +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 Load an ElGamal key with the wrong OID then + /// see ElGamal on + /// the Crypto++ wiki. + /// \sa Issue 876, + /// Issue 567 + 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: + ///
    + ///
  • 0 - using this object won't cause a crash or exception + ///
  • 1 - this object will probably function, and encrypt, sign, other + /// operations correctly + ///
  • 2 - ensure this object will function correctly, and perform + /// reasonable security checks + ///
  • 3 - perform reasonable security checks, and do checks that may + /// take a long time + ///
+ /// \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 ElGamalKeys provide the algorithm implementation ElGamal key +/// agreement and encryption schemes. +/// \details The ElGamalKeys class used DL_PrivateKey_GFP_OldFormat +/// and DL_PublicKey_GFP_OldFormat for the PrivateKey and +/// PublicKey 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 Load an ElGamal key with the wrong OID then +/// see ElGamal 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 Issue 876, +/// Issue 567, +/// Issue 1059 +/// \since Crypto++ 1.0 +struct ElGamalKeys +{ + /// \brief Implements DL_GroupParameters interface + typedef DL_CryptoKeys_ElGamal::GroupParameters GroupParameters; + /// \brief Implements DL_PrivateKey interface + typedef DL_PrivateKey_ElGamal PrivateKey; + /// \brief Implements DL_PublicKey interface + typedef DL_PublicKey_ElGamal 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 Load an ElGamal key with the wrong OID then +/// see ElGamal on +/// the Crypto++ wiki. +/// \sa Issue 876, +/// Issue 567 +/// \since Crypto++ 1.0 +struct ElGamal +{ + typedef DL_CryptoSchemeOptions 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; + /// \brief Implements PK_Encryptor interface + typedef PK_FinalTemplate, SchemeOptions, SchemeOptions::PublicKey> > Encryptor; + /// \brief Implements PK_Encryptor interface + typedef PK_FinalTemplate, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor; +}; + +typedef ElGamal::Encryptor ElGamalEncryptor; +typedef ElGamal::Decryptor ElGamalDecryptor; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/emsa2.h b/third_party/cryptoppwin/include/cryptopp/emsa2.h new file mode 100644 index 00000000..d39e73db --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/emsa2.h @@ -0,0 +1,101 @@ +// emsa2.h - originally written and placed in the public domain by Wei Dai + +/// \file emsa2.h +/// \brief Classes and functions for various padding schemes used in public key algorithms + +#ifndef CRYPTOPP_EMSA2_H +#define CRYPTOPP_EMSA2_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "hashfwd.h" +#include "misc.h" + +#ifdef CRYPTOPP_IS_DLL +# include "sha.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief EMSA2 hash identifier +/// \tparam H HashTransformation derived class +/// \since Crypto++ 5.0 +template class EMSA2HashId +{ +public: + static const byte id; +}; + +/// \brief EMSA2 padding method +/// \tparam BASE Message encoding method +/// \since Crypto++ 5.0 +template +class EMSA2HashIdLookup : public BASE +{ +public: + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier Lookup() + { + return HashIdentifier(&EMSA2HashId::id, 1); + } + }; + }; +}; + +// EMSA2HashId can be instantiated with the following classes. +// SHA1, SHA224, SHA256, SHA384, SHA512, RIPEMD128, RIPEMD160, Whirlpool + +#ifdef CRYPTOPP_IS_DLL +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +#endif + +// https://github.com/weidai11/cryptopp/issues/300 and +// https://github.com/weidai11/cryptopp/issues/533 +#if defined(__clang__) +template<> const byte EMSA2HashId::id; +template<> const byte EMSA2HashId::id; +template<> const byte EMSA2HashId::id; +template<> const byte EMSA2HashId::id; +template<> const byte EMSA2HashId::id; +#endif + +/// \brief EMSA2 padding method +/// \since Crypto++ 5.0 +class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "EMSA2";} + + size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const + {CRYPTOPP_UNUSED(hashIdentifierLength); return 8*digestLength + 31;} + + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +// EMSA2, for use with RWSS and RSA_ISO +// Only the following hash functions are supported by this signature standard: +// \dontinclude emsa2.h +// \skip EMSA2HashId can be instantiated +// \until end of list + +/// \brief EMSA2/P1363 padding method +/// \details Use with RWSS and RSA_ISO +/// \since Crypto++ 5.0 +struct P1363_EMSA2 : public SignatureStandard +{ + typedef EMSA2Pad SignatureMessageEncodingMethod; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/eprecomp.h b/third_party/cryptoppwin/include/cryptopp/eprecomp.h new file mode 100644 index 00000000..7049d4bd --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/eprecomp.h @@ -0,0 +1,162 @@ +// eprecomp.h - originally written and placed in the public domain by Wei Dai + +/// \file eprecomp.h +/// \brief Classes for precomputation in a group + +#ifndef CRYPTOPP_EPRECOMP_H +#define CRYPTOPP_EPRECOMP_H + +#include "cryptlib.h" +#include "integer.h" +#include "algebra.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief DL_GroupPrecomputation interface +/// \tparam T Field element +template +class DL_GroupPrecomputation +{ +public: + typedef T Element; + + virtual ~DL_GroupPrecomputation() {} + + /// \brief Determines if elements needs conversion + /// \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 + /// \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 + /// \return an element converted from an alternate representation + virtual Element ConvertOut(const Element &v) const {return v;} + + /// \brief Retrieves AbstractGroup interface + /// \return GetGroup() returns the AbstractGroup interface + virtual const AbstractGroup & GetGroup() const =0; + + /// \brief Decodes element in DER format + /// \param bt BufferedTransformation object + /// \return element in the group + virtual Element BERDecodeElement(BufferedTransformation &bt) const =0; + + /// \brief Encodes element in DER format + /// \param bt BufferedTransformation object + /// \param P Element to encode + virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0; +}; + +/// \brief DL_FixedBasePrecomputation interface +/// \tparam T Field element +template +class DL_FixedBasePrecomputation +{ +public: + typedef T Element; + + virtual ~DL_FixedBasePrecomputation() {} + + /// \brief Determines whether this object is initialized + /// \return true if this object is initialized, false otherwise + virtual bool IsInitialized() const =0; + + /// \brief Set the base element + /// \param group the group + /// \param base element in the group + virtual void SetBase(const DL_GroupPrecomputation &group, const Element &base) =0; + + /// \brief Get the base element + /// \param group the group + /// \return base element in the group + virtual const Element & GetBase(const DL_GroupPrecomputation &group) const =0; + + /// \brief Perform precomputation + /// \param group the group + /// \param maxExpBits used to calculate the exponent base + /// \param storage the suggested number of objects for the precompute table + /// \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. + /// \details If a derived class does not override Precompute(), then the base class throws + /// NotImplemented. + /// \sa SupportsPrecomputation(), LoadPrecomputation(), SavePrecomputation() + virtual void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) =0; + + /// \brief Retrieve previously saved precomputation + /// \param group the group + /// \param storedPrecomputation BufferedTransformation with the saved precomputation + /// \throw NotImplemented + /// \sa SupportsPrecomputation(), Precompute() + virtual void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) =0; + + /// \brief Save precomputation for later use + /// \param group the group + /// \param storedPrecomputation BufferedTransformation to write the precomputation + /// \throw NotImplemented + /// \sa SupportsPrecomputation(), Precompute() + virtual void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const =0; + + /// \brief Exponentiates an element + /// \param group the group + /// \param exponent the exponent + /// \return the result of the exponentiation + virtual Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const =0; + + /// \brief Exponentiates an element + /// \param pc1 the first the group precomputation + /// \param exponent1 the first exponent + /// \param pc2 the second the group precomputation + /// \param exponent2 the first exponent2 + /// \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 &pc1, const Integer &exponent1, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const =0; +}; + +/// \brief DL_FixedBasePrecomputation adapter class +/// \tparam T Field element +template +class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation +{ +public: + typedef T Element; + + virtual ~DL_FixedBasePrecomputationImpl() {} + + DL_FixedBasePrecomputationImpl() : m_windowSize(0) {} + + // DL_FixedBasePrecomputation + bool IsInitialized() const + {return !m_bases.empty();} + void SetBase(const DL_GroupPrecomputation &group, const Element &base); + const Element & GetBase(const DL_GroupPrecomputation &group) const + {return group.NeedConversions() ? m_base : m_bases[0];} + void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage); + void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation); + void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const; + Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const; + Element CascadeExponentiate(const DL_GroupPrecomputation &pc1, const Integer &exponent1, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const; + +private: + void PrepareCascade(const DL_GroupPrecomputation &group, std::vector > &eb, const Integer &exponent) const; + + Element m_base; + unsigned int m_windowSize; + Integer m_exponentBase; // what base to represent the exponent in + std::vector m_bases; // precalculated bases +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "eprecomp.cpp" +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/esign.h b/third_party/cryptoppwin/include/cryptopp/esign.h new file mode 100644 index 00000000..2c597c25 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/esign.h @@ -0,0 +1,169 @@ +// esign.h - originally written and placed in the public domain by Wei Dai + +/// \file esign.h +/// \brief Classes providing ESIGN signature schemes as defined in IEEE P1363a +/// \since Crypto++ 5.0 + +#ifndef CRYPTOPP_ESIGN_H +#define CRYPTOPP_ESIGN_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "integer.h" +#include "asn.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief ESIGN trapdoor function using the public key +/// \since Crypto++ 5.0 +class ESIGNFunction : public TrapdoorFunction, public ASN1CryptoMaterial +{ + typedef ESIGNFunction ThisClass; + +public: + + /// \brief Initialize a ESIGN public key with {n,e} + /// \param n the modulus + /// \param e the public exponent + void Initialize(const Integer &n, const Integer &e) + {m_n = n; m_e = e;} + + // PublicKey + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // TrapdoorFunction + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return m_n;} + Integer ImageBound() const {return Integer::Power2(GetK());} + + // non-derived + const Integer & GetModulus() const {return m_n;} + const Integer & GetPublicExponent() const {return m_e;} + + void SetModulus(const Integer &n) {m_n = n;} + void SetPublicExponent(const Integer &e) {m_e = e;} + +protected: + // Covertiy finding on overflow. The library allows small values for research purposes. + unsigned int GetK() const {return SaturatingSubtract(m_n.BitCount()/3, 1U);} + + Integer m_n, m_e; +}; + +/// \brief ESIGN trapdoor function using the private key +/// \since Crypto++ 5.0 +class InvertibleESIGNFunction : public ESIGNFunction, public RandomizedTrapdoorFunctionInverse, public PrivateKey +{ + typedef InvertibleESIGNFunction ThisClass; + +public: + + /// \brief Initialize a ESIGN private key with {n,e,p,q} + /// \param n modulus + /// \param e public exponent + /// \param p first prime factor + /// \param q second prime factor + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q) + {m_n = n; m_e = e; m_p = p; m_q = q;} + + /// \brief Create a ESIGN private key + /// \param rng a RandomNumberGenerator derived class + /// \param modulusBits the size of the modulud, 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. + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) + {GenerateRandomWithKeySize(rng, modulusBits);} + + // Squash Visual Studio C4250 warning + void Save(BufferedTransformation &bt) const + {BEREncode(bt);} + + // Squash Visual Studio C4250 warning + void Load(BufferedTransformation &bt) + {BERDecode(bt);} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const; + + // GeneratibleCryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + /*! parameters: (ModulusSize) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + +protected: + Integer m_p, m_q; +}; + +/// \brief EMSA5 padding method +/// \tparam T Mask Generation Function +/// \since Crypto++ 5.0 +template +class EMSA5Pad : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "EMSA5";} + + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const + { + CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength); + CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier); + SecByteBlock digest(hash.DigestSize()); + hash.Final(digest); + size_t representativeByteLength = BitsToBytes(representativeBitLength); + T mgf; + mgf.GenerateAndMask(hash, representative, representativeByteLength, digest, digest.size(), false); + if (representativeBitLength % 8 != 0) + representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); + } +}; + +/// \brief EMSA5 padding method, for use with ESIGN +/// \since Crypto++ 5.0 +struct P1363_EMSA5 : public SignatureStandard +{ + typedef EMSA5Pad SignatureMessageEncodingMethod; +}; + +/// \brief ESIGN keys +/// \since Crypto++ 5.0 +struct ESIGN_Keys +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "ESIGN";} + typedef ESIGNFunction PublicKey; + typedef InvertibleESIGNFunction PrivateKey; +}; + +/// \brief ESIGN signature scheme, IEEE P1363a +/// \tparam H HashTransformation derived class +/// \tparam STANDARD Signature encoding method +/// \since Crypto++ 5.0 +template +struct ESIGN : public TF_SS +{ +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/factory.h b/third_party/cryptoppwin/include/cryptopp/factory.h new file mode 100644 index 00000000..82dc5f58 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/factory.h @@ -0,0 +1,179 @@ +// factory.h - originally written and placed in the public domain by Wei Dai + +/// \file factory.h +/// \brief Classes and functions for registering and locating library objects + +#ifndef CRYPTOPP_OBJFACT_H +#define CRYPTOPP_OBJFACT_H + +#include "cryptlib.h" +#include "misc.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Object factory interface for registering objects +/// \tparam AbstractClass Base class interface of the object +template +class ObjectFactory +{ +public: + virtual ~ObjectFactory () {} + virtual AbstractClass * CreateObject() const =0; +}; + +/// \brief Object factory for registering objects +/// \tparam AbstractClass Base class interface of the object +/// \tparam ConcreteClass Class object +template +class DefaultObjectFactory : public ObjectFactory +{ +public: + AbstractClass * CreateObject() const + { + return new ConcreteClass; + } +}; + +/// \brief Object factory registry +/// \tparam AbstractClass Base class interface of the object +/// \tparam instance unique identifier +template +class ObjectFactoryRegistry +{ +public: + class FactoryNotFound : public Exception + { + public: + FactoryNotFound(const char *name) : Exception(OTHER_ERROR, std::string("ObjectFactoryRegistry: could not find factory for algorithm ") + name) {} + }; + + ~ObjectFactoryRegistry() + { + for (typename Map::iterator i = m_map.begin(); i != m_map.end(); ++i) + { + delete (ObjectFactory *)i->second; + i->second = NULLPTR; + } + } + + void RegisterFactory(const std::string &name, ObjectFactory *factory) + { + m_map[name] = factory; + } + + const ObjectFactory * GetFactory(const char *name) const + { + typename Map::const_iterator i = m_map.find(name); + return i == m_map.end() ? NULLPTR : (ObjectFactory *)i->second; + } + + AbstractClass *CreateObject(const char *name) const + { + const ObjectFactory *factory = GetFactory(name); + if (!factory) + throw FactoryNotFound(name); + return factory->CreateObject(); + } + + // Return a vector containing the factory names. This is easier than returning an iterator. + // from Andrew Pitonyak + std::vector GetFactoryNames() const + { + std::vector names; + typename Map::const_iterator iter; + for (iter = m_map.begin(); iter != m_map.end(); ++iter) + names.push_back(iter->first); + return names; + } + + CRYPTOPP_NOINLINE static ObjectFactoryRegistry & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT); + +private: + // use void * instead of ObjectFactory * to save code size + typedef std::map Map; + Map m_map; +}; + +template +ObjectFactoryRegistry & ObjectFactoryRegistry::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT) +{ + static ObjectFactoryRegistry s_registry; + return s_registry; +} + +/// \brief Object factory registry helper +/// \tparam AbstractClass Base class interface of the object +/// \tparam ConcreteClass Class object +/// \tparam instance unique identifier +template +struct RegisterDefaultFactoryFor +{ + RegisterDefaultFactoryFor(const char *name=NULLPTR) + { + // BCB2006 workaround + std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName()); + ObjectFactoryRegistry::Registry(). + RegisterFactory(n, new DefaultObjectFactory); + } +}; + +/// \fn RegisterAsymmetricCipherDefaultFactories +/// \brief Register asymmetric ciphers +/// \tparam SchemeClass interface of the object under a scheme +/// \details Schemes include asymmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// signature schemes (registers SchemeClass::Signer and SchemeClass::Verifier), +/// symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// authenticated symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), etc. +template +void RegisterAsymmetricCipherDefaultFactories(const char *name=NULLPTR) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +/// \fn RegisterSignatureSchemeDefaultFactories +/// \brief Register signature schemes +/// \tparam SchemeClass interface of the object under a scheme +/// \details Schemes include asymmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// signature schemes (registers SchemeClass::Signer and SchemeClass::Verifier), +/// symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// authenticated symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), etc. +template +void RegisterSignatureSchemeDefaultFactories(const char *name=NULLPTR) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +/// \fn RegisterSymmetricCipherDefaultFactories +/// \brief Register symmetric ciphers +/// \tparam SchemeClass interface of the object under a scheme +/// \details Schemes include asymmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// signature schemes (registers SchemeClass::Signer and SchemeClass::Verifier), +/// symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// authenticated symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), etc. +template +void RegisterSymmetricCipherDefaultFactories(const char *name=NULLPTR) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +/// \fn RegisterAuthenticatedSymmetricCipherDefaultFactories +/// \brief Register authenticated symmetric ciphers +/// \tparam SchemeClass interface of the object under a scheme +/// \details Schemes include asymmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// signature schemes (registers SchemeClass::Signer and SchemeClass::Verifier), +/// symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), +/// authenticated symmetric ciphers (registers SchemeClass::Encryptor and SchemeClass::Decryptor), etc. +template +void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULLPTR) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/fhmqv.h b/third_party/cryptoppwin/include/cryptopp/fhmqv.h new file mode 100644 index 00000000..505d2861 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/fhmqv.h @@ -0,0 +1,408 @@ +// fhmqv.h - written and placed in the public domain by Jeffrey Walton, Ray Clayton and Uri Blumenthal +// Shamelessly based upon Wei Dai's MQV source files + +#ifndef CRYPTOPP_FHMQV_H +#define CRYPTOPP_FHMQV_H + +/// \file fhmqv.h +/// \brief Classes for Fully Hashed Menezes-Qu-Vanstone key agreement in GF(p) +/// \since Crypto++ 5.6.4 + +#include "gfpcrypt.h" +#include "algebra.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Fully Hashed Menezes-Qu-Vanstone in GF(p) +/// \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's +/// A Secure and Efficient Authenticated Diffie-Hellman Protocol. +/// Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. +/// \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain +/// \since Crypto++ 5.6.4 +template +class FHMQV_Domain : public AuthenticatedKeyAgreementDomain +{ +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef FHMQV_Domain Domain; + + virtual ~FHMQV_Domain() {} + + /// \brief Construct a FHMQV domain + /// \param clientRole flag indicating initiator or recipient + /// \details clientRole = true indicates initiator, and + /// clientRole = false 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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + FHMQV_Domain(const GroupParameters ¶ms, 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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + FHMQV_Domain(T1 v1, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + 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);} + +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;} + + /// \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 GetEncodedElementSize(false), + /// 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 GetEncodedElementSize(true), + /// 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 + /// [1,MaxExponent()]. + /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength() + void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + } + + /// \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 COUNTOF(publicKey) == PublicStaticKeyLength() + void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + 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 COUNTOF(privateKey) == EphemeralPrivateKeyLength() + void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(rng, Integer::One(), params.GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + 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 COUNTOF(publicKey) == EphemeralPublicKeyLength() + void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + 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. + /// validateStaticOtherPublicKey determines how thoroughly other's + /// static public key is validated. If you have previously validated the + /// couterparty's static public key, then use + /// validateStaticOtherPublicKey=false to save time. + /// \pre COUNTOF(agreedValue) == AgreedValueLength() + /// \pre COUNTOF(staticPrivateKey) == StaticPrivateKeyLength() + /// \pre COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength() + /// \pre COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength() + /// \pre COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength() + bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const + { + 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 + // (long term) public key. AA or BB will then point into tt. + SecByteBlock tt(StaticPublicKeyLength()); + + try + { + this->GetMaterial().DoQuickSanityCheck(); + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + + if(m_role == RoleServer) + { + Integer b(staticPrivateKey, StaticPrivateKeyLength()); + Element B = params.ExponentiateBase(b); + params.EncodeElement(true, B, tt); + + XX = ephemeralOtherPublicKey; + xxs = EphemeralPublicKeyLength(); + YY = ephemeralPrivateKey + StaticPrivateKeyLength(); + yys = EphemeralPublicKeyLength(); + AA = staticOtherPublicKey; + aas = StaticPublicKeyLength(); + BB = tt.BytePtr(); + bbs = tt.SizeInBytes(); + } + else + { + Integer a(staticPrivateKey, StaticPrivateKeyLength()); + Element A = params.ExponentiateBase(a); + params.EncodeElement(true, A, tt); + + XX = ephemeralPrivateKey + StaticPrivateKeyLength(); + xxs = EphemeralPublicKeyLength(); + YY = ephemeralOtherPublicKey; + yys = EphemeralPublicKeyLength(); + AA = tt.BytePtr(); + aas = tt.SizeInBytes(); + BB = staticOtherPublicKey; + bbs = StaticPublicKeyLength(); + } + + 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); + SecByteBlock dd(len), ee(len); + + Hash(NULLPTR, XX, xxs, YY, yys, AA, aas, BB, bbs, dd.BytePtr(), dd.SizeInBytes()); + Integer d(dd.BytePtr(), dd.SizeInBytes()); + + Hash(NULLPTR, YY, yys, XX, xxs, AA, aas, BB, bbs, ee.BytePtr(), ee.SizeInBytes()); + Integer e(ee.BytePtr(), ee.SizeInBytes()); + + Element sigma; + if(m_role == RoleServer) + { + Integer y(ephemeralPrivateKey, StaticPrivateKeyLength()); + Integer b(staticPrivateKey, StaticPrivateKeyLength()); + Integer s_B = (y + e * b) % q; + + Element A = params.DecodeElement(AA, false); + Element X = params.DecodeElement(XX, false); + + Element t1 = params.ExponentiateElement(A, d); + Element t2 = m_groupParameters.MultiplyElements(X, t1); + + sigma = params.ExponentiateElement(t2, s_B); + } + else + { + Integer x(ephemeralPrivateKey, StaticPrivateKeyLength()); + Integer a(staticPrivateKey, StaticPrivateKeyLength()); + Integer s_A = (x + d * a) % q; + + 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); + + sigma = params.ExponentiateElement(t2, s_A); + } + + Hash(&sigma, XX, xxs, YY, yys, AA, aas, BB, bbs, agreedValue, AgreedValueLength()); + } + catch (DL_BadElement &) + { + CRYPTOPP_ASSERT(0); + return false; + } + return true; + } + +protected: + + inline void Hash(const Element* sigma, + const byte* e1, size_t e1len, const byte* e2, size_t e2len, + const byte* s1, size_t s1len, const byte* s2, size_t s2len, + byte* digest, size_t dlen) const + { + HASH hash; + size_t idx = 0, req = dlen; + size_t blk = STDMIN(dlen, (size_t)HASH::DIGESTSIZE); + + if(sigma) + { + //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()); + } + + hash.Update(e1, e1len); + hash.Update(e2, e2len); + hash.Update(s1, s1len); + hash.Update(s2, s2len); + + hash.TruncatedFinal(digest, blk); + req -= blk; + + // All this to catch tail bytes for large curves and small hashes + while(req != 0) + { + hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); + + idx += (size_t)HASH::DIGESTSIZE; + blk = STDMIN(req, (size_t)HASH::DIGESTSIZE); + hash.TruncatedFinal(&digest[idx], blk); + + req -= blk; + } + } + +private: + + // The paper uses Initiator and Recipient - make it classical. + enum KeyAgreementRole { RoleServer = 1, RoleClient }; + + DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} + const DL_GroupParameters & GetAbstractGroupParameters() const{return m_groupParameters;} + + GroupParameters m_groupParameters; + KeyAgreementRole m_role; +}; + +/// \brief Fully Hashed Menezes-Qu-Vanstone in GF(p) +/// \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's +/// A Secure and Efficient Authenticated Diffie-Hellman Protocol. +/// Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. +/// \sa FHMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain +/// \since Crypto++ 5.6.4 +typedef FHMQV_Domain FHMQV; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/files.h b/third_party/cryptoppwin/include/cryptopp/files.h new file mode 100644 index 00000000..c09da5a5 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/files.h @@ -0,0 +1,181 @@ +// files.h - originally written and placed in the public domain by Wei Dai + +/// \file files.h +/// \brief Classes providing file-based library services +/// \since Crypto++ 1.0 + +#ifndef CRYPTOPP_FILES_H +#define CRYPTOPP_FILES_H + +#include "cryptlib.h" +#include "filters.h" +#include "argnames.h" +#include "smartptr.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Implementation of Store interface +/// \details file-based implementation of Store interface +class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable +{ +public: + /// \brief Exception thrown when file-based error is encountered + class Err : public Exception + { + public: + Err(const std::string &s) : Exception(IO_ERROR, s) {} + }; + /// \brief Exception thrown when file-based open error is encountered + class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}}; + /// \brief Exception thrown when file-based read error is encountered + class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}}; + + /// \brief Construct a FileStore + FileStore() : m_stream(NULLPTR), m_space(NULLPTR), m_len(0), m_waiting(0) {} + + /// \brief Construct a FileStore + /// \param in an existing stream + FileStore(std::istream &in) : m_stream(NULLPTR), m_space(NULLPTR), m_len(0), m_waiting(0) + {StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));} + + /// \brief Construct a FileStore + /// \param filename the narrow name of the file to open + 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) || (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. + FileStore(const wchar_t *filename) + {StoreInitialize(MakeParameters(Name::InputFileNameWide(), filename));} +#endif + + /// \brief Retrieves the internal stream + /// \return the internal stream pointer + std::istream* GetStream() {return m_stream;} + + /// \brief Retrieves the internal stream + /// \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; + lword Skip(lword skipMax=ULONG_MAX); + +private: + void StoreInitialize(const NameValuePairs ¶meters); + + member_ptr m_file; + std::istream *m_stream; + byte *m_space; + size_t m_len; + bool m_waiting; +}; + +/// \brief Implementation of Store interface +/// \details file-based implementation of Store interface +class CRYPTOPP_DLL FileSource : public SourceTemplate +{ +public: + typedef FileStore::Err Err; + typedef FileStore::OpenErr OpenErr; + typedef FileStore::ReadErr ReadErr; + + /// \brief Construct a FileSource + FileSource(BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {} + + /// \brief Construct a FileSource + /// \param in an existing stream + /// \param pumpAll flag indicating if source data should be pumped to its attached transformation + /// \param attachment an optional attached transformation + FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));} + + /// \brief Construct a FileSource + /// \param filename the narrow name of the file to open + /// \param pumpAll flag indicating if source data should be pumped to its attached transformation + /// \param attachment an optional attached transformation + /// \param binary flag indicating if the file is binary + FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULLPTR, bool binary=true) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));} + +#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 + /// \param attachment an optional attached transformation + /// \param binary flag indicating if the file is binary + /// \details On non-Windows OS, this function assumes that setlocale() has been called. + FileSource(const wchar_t *filename, bool pumpAll, BufferedTransformation *attachment = NULLPTR, bool binary=true) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileNameWide(), filename)(Name::InputBinaryMode(), binary));} +#endif + + /// \brief Retrieves the internal stream + /// \return the internal stream pointer + std::istream* GetStream() {return m_store.GetStream();} +}; + +/// \brief Implementation of Store interface +/// \details file-based implementation of Sink interface +class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable +{ +public: + /// \brief Exception thrown when file-based error is encountered + class Err : public Exception + { + public: + Err(const std::string &s) : Exception(IO_ERROR, s) {} + }; + /// \brief Exception thrown when file-based open error is encountered + class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}}; + /// \brief Exception thrown when file-based write error is encountered + class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}}; + + /// \brief Construct a FileSink + FileSink() : m_stream(NULLPTR) {} + + /// \brief Construct a FileSink + /// \param out an existing stream + FileSink(std::ostream &out) + {IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));} + + /// \brief Construct a FileSink + /// \param filename the narrow name of the file to open + /// \param binary flag indicating if the file is binary + FileSink(const char *filename, bool binary=true) + {IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)(Name::OutputBinaryMode(), binary));} + +#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. + FileSink(const wchar_t *filename, bool binary=true) + {IsolatedInitialize(MakeParameters(Name::OutputFileNameWide(), filename)(Name::OutputBinaryMode(), binary));} +#endif + + /// \brief Retrieves the internal stream + /// \return the internal stream pointer + std::ostream* GetStream() {return m_stream;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedFlush(bool hardFlush, bool blocking); + +private: + member_ptr m_file; + std::ostream *m_stream; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/filters.h b/third_party/cryptoppwin/include/cryptopp/filters.h new file mode 100644 index 00000000..0de46c41 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/filters.h @@ -0,0 +1,1529 @@ +// filters.h - originally written and placed in the public domain by Wei Dai + +/// \file filters.h +/// \brief Implementation of BufferedTransformation's attachment interface. + +#ifndef CRYPTOPP_FILTERS_H +#define CRYPTOPP_FILTERS_H + +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4127 4189 4231 4275 4514) +#endif + +#include "cryptlib.h" +#include "simple.h" +#include "secblock.h" +#include "misc.h" +#include "smartptr.h" +#include "queue.h" +#include "algparam.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Implementation of BufferedTransformation's attachment interface +/// \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. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable +{ +public: + virtual ~Filter() {} + + /// \name ATTACHMENT + //@{ + + /// \brief Construct a Filter + /// \param attachment an optional attached transformation + /// \details attachment can be NULL. + Filter(BufferedTransformation *attachment = NULLPTR); + + /// \brief Determine if attachable + /// \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 + /// \return pointer to a BufferedTransformation if there is an attached transformation, NULL otherwise. + BufferedTransformation *AttachedTransformation(); + + /// \brief Retrieve attached transformation + /// \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 NULL. + /// Pass NULL to remove an existing BufferedTransformation or chain of filters + void Detach(BufferedTransformation *newAttachment = NULLPTR); + + //@} + + /// \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; + + //@} + + /// \name SIGNALS + //@{ + + // BufferedTransformation in cryptlib.h + void Initialize(const NameValuePairs ¶meters=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 + + virtual bool ShouldPropagateMessageEnd() const {return true;} + virtual bool ShouldPropagateMessageSeriesEnd() const {return true;} + + void PropagateInitialize(const NameValuePairs ¶meters, int propagation); + + /// \brief Forward processed data on to attached transformation + /// \param outputSite unknown, system crash between keyboard and chair... + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \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 + /// \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. + /// \param outputSite unknown, system crash between keyboard and chair... + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \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 + /// \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 + /// \param outputSite unknown, system crash between keyboard and chair... + /// \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 + /// \return true is the MessageEnd signal was successful, false otherwise. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 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 + /// \param outputSite unknown, system crash between keyboard and chair... + /// \param hardFlush is used to indicate whether all data should be flushed + /// \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 + /// \return true is the Flush signal was successful, false otherwise. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 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. + /// \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. + 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 + /// \param outputSite unknown, system crash between keyboard and chair... + /// \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 + /// \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. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 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); + +private: + member_ptr m_attachment; + +protected: + size_t m_inputPosition; + int m_continueAt; +}; + +/// \brief Create a working space in a BufferedTransformation +struct CRYPTOPP_DLL FilterPutSpaceHelper +{ + virtual ~FilterPutSpaceHelper() {} + + /// \brief Create a working space in a BufferedTransformation + /// \param target BufferedTransformation for the working space + /// \param channel channel for the working space + /// \param minSize minimum size of the allocation, in bytes + /// \param desiredSize preferred size of the allocation, in bytes + /// \param bufferSize actual size of the allocation, in bytes + /// \pre desiredSize >= minSize and bufferSize >= minSize. + /// \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 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); + if (m_tempSpace.size() < minSize) + { + byte *result = target.ChannelCreatePutSpace(channel, desiredSize); + if (desiredSize >= minSize) + { + bufferSize = desiredSize; + return result; + } + m_tempSpace.New(bufferSize); + } + + bufferSize = m_tempSpace.size(); + return m_tempSpace.begin(); + } + + /// \brief Create a working space in a BufferedTransformation + /// \param target the BufferedTransformation for the working space + /// \param channel channel for the working space + /// \param minSize minimum size of the allocation, in bytes + /// \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);} + + /// \brief Create a working space in a BufferedTransformation + /// \param target the BufferedTransformation for the working space + /// \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() 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 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. +class CRYPTOPP_DLL MeterFilter : public Bufferless +{ +public: + virtual ~MeterFilter() {} + + /// \brief Construct a MeterFilter + /// \param attachment an optional attached transformation + /// \param transparent flag indicating if the filter should function transparently + /// \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) + , m_begin(NULLPTR), m_length(0) {Detach(attachment); ResetMeter();} + + /// \brief Set or change the transparent mode of this object + /// \param transparent the new transparent mode + void SetTransparent(bool transparent) {m_transparent = transparent;} + + /// \brief Adds a range to skip during processing + /// \param message the message to apply the range + /// \param position the 0-based index in the current stream + /// \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. + 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. + void ResetMeter(); + + // BufferedTransformation in cryptlib.h + void IsolatedInitialize(const NameValuePairs ¶meters) + {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;} + + // 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); + +private: + size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable); + bool ShouldPropagateMessageEnd() const {return m_transparent;} + bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;} + + struct MessageRange + { + inline bool operator<(const MessageRange &b) const // BCB2006 workaround: this has to be a member function + {return message < b.message || (message == b.message && position < b.position);} + unsigned int message; lword position; lword size; + }; + + bool m_transparent; + lword m_currentMessageBytes, m_totalBytes; + unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries; + std::deque m_rangesToSkip; + byte *m_begin; + size_t m_length; +}; + +/// \brief A transparent MeterFilter +/// \sa MeterFilter, OpaqueFilter +class CRYPTOPP_DLL TransparentFilter : public MeterFilter +{ +public: + /// \brief Construct a TransparentFilter + /// \param attachment an optional attached transformation + TransparentFilter(BufferedTransformation *attachment=NULLPTR) : MeterFilter(attachment, true) {} +}; + +/// \brief A non-transparent MeterFilter +/// \sa MeterFilter, TransparentFilter +class CRYPTOPP_DLL OpaqueFilter : public MeterFilter +{ +public: + /// \brief Construct an OpaqueFilter + /// \param attachment an optional attached transformation + OpaqueFilter(BufferedTransformation *attachment=NULLPTR) : MeterFilter(attachment, false) {} +}; + +/// \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. blockSize == 1). +/// \sa AuthenticatedEncryptionFilter, AuthenticatedDecryptionFilter, HashVerificationFilter, +/// SignatureVerificationFilter, StreamTransformationFilter +class CRYPTOPP_DLL FilterWithBufferedInput : public Filter +{ +public: + virtual ~FilterWithBufferedInput() {} + + /// \brief Construct a FilterWithBufferedInput with an attached transformation + /// \param attachment an attached transformation + FilterWithBufferedInput(BufferedTransformation *attachment); + + /// \brief Construct a FilterWithBufferedInput with an attached transformation + /// \param firstSize the size of the first block + /// \param blockSize the size of middle blocks + /// \param lastSize the size of the last block + /// \param attachment an attached transformation + /// \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 ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + return PutMaybeModifiable(const_cast(inString), length, messageEnd, blocking, false); + } + + size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) + { + return PutMaybeModifiable(inString, length, messageEnd, blocking, true); + } + + /// \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 lastSize != 0. + /// ForceNextPut() forces a call to NextPut() if this is the case. + void ForceNextPut(); + +protected: + virtual bool DidFirstPut() const {return m_firstInputDone;} + virtual size_t GetFirstPutSize() const {return m_firstSize;} + virtual size_t GetBlockPutSize() const {return m_blockSize;} + virtual size_t GetLastPutSize() const {return m_lastSize;} + + virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) + {CRYPTOPP_UNUSED(parameters); CRYPTOPP_UNUSED(firstSize); CRYPTOPP_UNUSED(blockSize); CRYPTOPP_UNUSED(lastSize); InitializeDerived(parameters);} + virtual void InitializeDerived(const NameValuePairs ¶meters) + {CRYPTOPP_UNUSED(parameters);} + // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize) + // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received)). + // inString is m_firstSize in length. + virtual void FirstPut(const byte *inString) =0; + // NextPut() is called if totalLength >= firstSize+blockSize+lastSize + virtual void NextPutSingle(const byte *inString) + {CRYPTOPP_UNUSED(inString); CRYPTOPP_ASSERT(false);} + // Same as NextPut() except length can be a multiple of blockSize + // Either NextPut() or NextPutMultiple() must be overridden + virtual void NextPutMultiple(const byte *inString, size_t length); + // Same as NextPutMultiple(), but inString can be modified + virtual void NextPutModifiable(byte *inString, size_t length) + {NextPutMultiple(inString, length);} + /// \brief Input the last block of data + /// \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: + ///
+	///     if totalLength < firstSize then length == totalLength
+	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
+	///     else lastSize <= length < lastSize+blockSize
+	/// 
+ virtual void LastPut(const byte *inString, size_t length) =0; + virtual void FlushDerived() {} + +protected: + size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable); + void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable) + { + if (modifiable) NextPutModifiable(inString, length); + else NextPutMultiple(inString, length); + } + + // This function should no longer be used, put this here to cause a compiler error + // if someone tries to override NextPut(). + virtual int NextPut(const byte *inString, size_t length) + {CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); CRYPTOPP_ASSERT(false); return 0;} + + class BlockQueue + { + public: + void ResetQueue(size_t blockSize, size_t maxBlocks); + byte *GetBlock(); + byte *GetContigousBlocks(size_t &numberOfBytes); + size_t GetAll(byte *outString); + void Put(const byte *inString, size_t length); + size_t CurrentSize() const {return m_size;} + size_t MaxSize() const {return m_buffer.size();} + + private: + SecByteBlock m_buffer; + size_t m_blockSize, m_maxBlocks, m_size; + byte *m_begin; + }; + + size_t m_firstSize, m_blockSize, m_lastSize; + bool m_firstInputDone; + BlockQueue m_queue; +}; + +/// \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. +class CRYPTOPP_DLL FilterWithInputQueue : public Filter +{ +public: + virtual ~FilterWithInputQueue() {} + + /// \brief Construct a FilterWithInputQueue + /// \param attachment an optional attached transformation + FilterWithInputQueue(BufferedTransformation *attachment=NULLPTR) : Filter(attachment) {} + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + if (!blocking) + throw BlockingInputOnly("FilterWithInputQueue"); + + m_inQueue.Put(inString, length); + if (messageEnd) + { + IsolatedMessageEnd(blocking); + Output(0, NULLPTR, 0, messageEnd, blocking); + } + return 0; + } + +protected: + virtual bool IsolatedMessageEnd(bool blocking) =0; + void IsolatedInitialize(const NameValuePairs ¶meters) + {CRYPTOPP_UNUSED(parameters); m_inQueue.Clear();} + + ByteQueue m_inQueue; +}; + +/// \struct BlockPaddingSchemeDef +/// \brief Padding schemes used for block ciphers +/// \since Crypto++ 5.0 +struct BlockPaddingSchemeDef +{ + /// \enum BlockPaddingScheme + /// \brief Padding schemes used for block ciphers. + /// \details DEFAULT_PADDING means PKCS_PADDING if cipher.MandatoryBlockSize() > 1 && + /// cipher.MinLastBlockSize() == 0, which holds for ECB or CBC mode. Otherwise, + /// NO_PADDING for modes like OFB, CFB, CTR, CBC-CTS. + /// \sa Block Cipher Padding for + /// additional details. + /// \since Crypto++ 5.0 + enum BlockPaddingScheme { + /// \brief No padding added to a block + /// \since Crypto++ 5.0 + NO_PADDING, + /// \brief 0's padding added to a block + /// \since Crypto++ 5.0 + ZEROS_PADDING, + /// \brief PKCS padding added to a block + /// \since Crypto++ 5.0 + PKCS_PADDING, + /// \brief 1 and 0's padding added to a block + /// \since Crypto++ 5.0 + ONE_AND_ZEROS_PADDING, + /// \brief W3C padding added to a block + /// \sa XML + /// Encryption Syntax and Processing + /// \since Crypto++ 6.0 + W3C_PADDING, + /// \brief Default padding scheme + /// \since Crypto++ 5.0 + DEFAULT_PADDING + }; +}; + +/// \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() +/// \since Crypto++ 5.0 +class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper +{ +public: + virtual ~StreamTransformationFilter() {} + + /// \brief Construct a StreamTransformationFilter + /// \param c reference to a StreamTransformation + /// \param attachment an optional attached transformation + /// \param padding the \ref BlockPaddingSchemeDef "padding scheme" + /// \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); + + std::string AlgorithmName() const {return m_cipher.AlgorithmName();} + +protected: + + friend class AuthenticatedEncryptionFilter; + friend class AuthenticatedDecryptionFilter; + + /// \brief Construct a StreamTransformationFilter + /// \param c reference to a StreamTransformation + /// \param attachment an optional attached transformation + /// \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(). + StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool authenticated); + + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void NextPutModifiable(byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + + static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding); + + StreamTransformation &m_cipher; + BlockPaddingScheme m_padding; + unsigned int m_mandatoryBlockSize; + unsigned int m_optimalBufferSize; + unsigned int m_reservedBufferSize; + bool m_isSpecial; +}; + +/// \brief Filter wrapper for HashTransformation +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL HashFilter : public Bufferless, private FilterPutSpaceHelper +{ +public: + virtual ~HashFilter() {} + + /// \brief Construct a HashFilter + /// \param hm reference to a HashTransformation + /// \param attachment an optional attached transformation + /// \param putMessage flag indicating whether the original message should be passed to an attached transformation + /// \param truncatedDigestSize the size of the digest + /// \param messagePutChannel the channel on which the message should be output + /// \param hashPutChannel the channel on which the digest should be output + HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULLPTR, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL); + + std::string AlgorithmName() const {return m_hashModule.AlgorithmName();} + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);} + +private: + HashTransformation &m_hashModule; + bool m_putMessage; + unsigned int m_digestSize; + byte *m_space; + std::string m_messagePutChannel, m_hashPutChannel; +}; + +/// \brief Filter wrapper for HashTransformation +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput +{ +public: + virtual ~HashVerificationFilter() {} + + /// \brief Exception thrown when a data integrity check failure is encountered + class HashVerificationFailed : public Exception + { + public: + HashVerificationFailed() + : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {} + }; + + /// \enum Flags + /// \brief Flags controlling filter behavior. + /// \details The flags are a bitmask and can be OR'd together. + enum Flags { + /// \brief The hash is at the end of the message (i.e., concatenation of message+hash) + HASH_AT_END=0, + /// \brief The hash is at the beginning of the message (i.e., concatenation of hash+message) + HASH_AT_BEGIN=1, + /// \brief The message should be passed to an attached transformation + PUT_MESSAGE=2, + /// \brief The hash should be passed to an attached transformation + PUT_HASH=4, + /// \brief The result of the verification should be passed to an attached transformation + PUT_RESULT=8, + /// \brief The filter should throw a HashVerificationFailed if a failure is encountered + THROW_EXCEPTION=16, + /// \brief Default flags using HASH_AT_BEGIN and PUT_RESULT + DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT + }; + + /// \brief Construct a HashVerificationFilter + /// \param hm reference to a HashTransformation + /// \param attachment an optional attached transformation + /// \param flags flags indicating behaviors for the filter + /// \param truncatedDigestSize the size of the digest + /// \details truncatedDigestSize = -1 indicates \ref HashTransformation::DigestSize() "DigestSize" should be used. + HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULLPTR, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1); + + std::string AlgorithmName() const {return m_hashModule.AlgorithmName();} + bool GetLastResult() const {return m_verified;} + +protected: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + +private: + friend class AuthenticatedDecryptionFilter; + + HashTransformation &m_hashModule; + word32 m_flags; + unsigned int m_digestSize; + bool m_verified; + SecByteBlock m_expectedHash; +}; + +/// \brief Filter wrapper for encrypting with 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 Issue 817 and Commit ff110c6e183e. +/// \sa AuthenticatedSymmetricCipher, AuthenticatedDecryptionFilter, EAX, CCM, GCM, +/// and AadSource on the +/// Crypto++ wiki. +/// \since Crypto++ 5.6.0 +class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter +{ +public: + virtual ~AuthenticatedEncryptionFilter() {} + + /// \brief Construct a AuthenticatedEncryptionFilter + /// \param c reference to a AuthenticatedSymmetricCipher + /// \param attachment an optional attached transformation + /// \param putAAD flag indicating whether the AAD should be passed to an attached transformation + /// \param truncatedDigestSize the size of the digest + /// \param macChannel the channel on which the MAC should be output + /// \param padding the \ref BlockPaddingSchemeDef "padding scheme" + /// \details truncatedDigestSize = -1 indicates \ref HashTransformation::DigestSize() "DigestSize" should be used. + /// \since Crypto++ 5.6.0 + AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULLPTR, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING); + + void IsolatedInitialize(const NameValuePairs ¶meters); + 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); + + /// \brief Input the last block of data + /// \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: + ///
+	///     if totalLength < firstSize then length == totalLength
+	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
+	///     else lastSize <= length < lastSize+blockSize
+	/// 
+ void LastPut(const byte *inString, size_t length); + +protected: + HashFilter m_hf; +}; + +/// \brief Filter wrapper for decrypting with 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 Issue 817 and Commit ff110c6e183e. +/// \sa AuthenticatedSymmetricCipher, AuthenticatedEncryptionFilter, EAX, CCM, GCM, +/// and AadSource on the +/// Crypto++ wiki. +/// \since Crypto++ 5.6.0 +class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef +{ +public: + /// \enum Flags + /// \brief Flags controlling filter behavior. + /// \details The flags are a bitmask and can be OR'd together. + enum Flags { + /// \brief The MAC is at the end of the message (i.e., concatenation of message+mac) + MAC_AT_END=0, + /// \brief The MAC is at the beginning of the message (i.e., concatenation of mac+message) + MAC_AT_BEGIN=1, + /// \brief The filter should throw a HashVerificationFailed if a failure is encountered + THROW_EXCEPTION=16, + /// \brief Default flags using THROW_EXCEPTION + DEFAULT_FLAGS = THROW_EXCEPTION + }; + + virtual ~AuthenticatedDecryptionFilter() {} + + /// \brief Construct a AuthenticatedDecryptionFilter + /// \param c reference to a AuthenticatedSymmetricCipher + /// \param attachment an optional attached transformation + /// \param flags flags indicating behaviors for the filter + /// \param truncatedDigestSize the size of the digest + /// \param padding the \ref BlockPaddingSchemeDef "padding scheme" + /// \details Additional authenticated data should be given in channel "AAD". + /// \details truncatedDigestSize = -1 indicates \ref HashTransformation::DigestSize() "DigestSize" should be used. + /// \since Crypto++ 5.6.0 + AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULLPTR, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING); + + 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: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + + /// \brief Input the last block of data + /// \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: + ///
+	///     if totalLength < firstSize then length == totalLength
+	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
+	///     else lastSize <= length < lastSize+blockSize
+	/// 
+ void LastPut(const byte *inString, size_t length); + + HashVerificationFilter m_hashVerifier; + StreamTransformationFilter m_streamFilter; +}; + +/// \brief Filter wrapper for PK_Signer +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL SignerFilter : public Unflushable +{ +public: + virtual ~SignerFilter() {} + + /// \brief Construct a SignerFilter + /// \param rng a RandomNumberGenerator derived class + /// \param signer a PK_Signer derived class + /// \param attachment an optional attached transformation + /// \param putMessage flag indicating whether the original message should be passed to an attached transformation + SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULLPTR, bool putMessage=false) + : m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);} + + std::string AlgorithmName() const {return m_signer.AlgorithmName();} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + +private: + RandomNumberGenerator &m_rng; + const PK_Signer &m_signer; + member_ptr m_messageAccumulator; + bool m_putMessage; + SecByteBlock m_buf; +}; + +/// \brief Filter wrapper for PK_Verifier +/// \details This filter was formerly named VerifierFilter. The name changed at Crypto++ 5.0. +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput +{ +public: + /// \brief Exception thrown when an invalid signature is encountered + class SignatureVerificationFailed : public Exception + { + public: + SignatureVerificationFailed() + : Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {} + }; + + /// \enum Flags + /// \brief Flags controlling filter behavior. + /// \details The flags are a bitmask and can be OR'd together. + enum Flags { + /// \brief The signature is at the end of the message (i.e., concatenation of message+signature) + SIGNATURE_AT_END=0, + /// \brief The signature is at the beginning of the message (i.e., concatenation of signature+message) + SIGNATURE_AT_BEGIN=1, + /// \brief The message should be passed to an attached transformation + PUT_MESSAGE=2, + /// \brief The signature should be passed to an attached transformation + PUT_SIGNATURE=4, + /// \brief The result of the verification should be passed to an attached transformation + PUT_RESULT=8, + /// \brief The filter should throw a HashVerificationFailed if a failure is encountered + THROW_EXCEPTION=16, + /// \brief Default flags using SIGNATURE_AT_BEGIN and PUT_RESULT + DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT + }; + + virtual ~SignatureVerificationFilter() {} + + /// \brief Construct a SignatureVerificationFilter + /// \param verifier a PK_Verifier derived class + /// \param attachment an optional attached transformation + /// \param flags flags indicating behaviors for the filter + SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULLPTR, word32 flags = DEFAULT_FLAGS); + + std::string AlgorithmName() const {return m_verifier.AlgorithmName();} + + /// \brief Retrieves the result of the last verification + /// \return true if the signature on the previosus message was valid, false otherwise + bool GetLastResult() const {return m_verified;} + +protected: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + +private: + const PK_Verifier &m_verifier; + member_ptr m_messageAccumulator; + word32 m_flags; + SecByteBlock m_signature; + bool m_verified; +}; + +/// \brief Redirect input to another BufferedTransformation without owning it +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL Redirector : public CustomSignalPropagation +{ +public: + /// \enum Behavior + /// \brief Controls signal propagation behavior + enum Behavior + { + /// \brief Pass data only + DATA_ONLY = 0x00, + /// \brief Pass signals + PASS_SIGNALS = 0x01, + /// \brief Pass wait events + PASS_WAIT_OBJECTS = 0x02, + /// \brief Pass everything + /// \details PASS_EVERYTHING is default + PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS + }; + + virtual ~Redirector() {} + + /// \brief Construct a Redirector + Redirector() : m_target(NULLPTR), m_behavior(PASS_EVERYTHING) {} + + /// \brief Construct a Redirector + /// \param target the destination BufferedTransformation + /// \param behavior Behavior "flags" specifying signal propagation + Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING) + : m_target(&target), m_behavior(behavior) {} + + /// \brief Redirect input to another BufferedTransformation + /// \param target the destination BufferedTransformation + void Redirect(BufferedTransformation &target) {m_target = ⌖} + /// \brief Stop redirecting input + void StopRedirection() {m_target = NULLPTR;} + + /// \brief Retrieve signal propagation behavior + /// \return the current signal propagation behavior + Behavior GetBehavior() {return static_cast(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;} + /// \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(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;} + /// \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(PASS_WAIT_OBJECTS); } + + bool CanModifyInput() const + {return m_target ? m_target->CanModifyInput() : false;} + + void Initialize(const NameValuePairs ¶meters, int propagation); + byte * CreatePutSpace(size_t &size) + { + if (m_target) + return m_target->CreatePutSpace(size); + else + { + size = 0; + return NULLPTR; + } + } + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + {return m_target ? m_target->Put2(inString, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;} + bool MessageSeriesEnd(int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;} + + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) + { + if (m_target) + return m_target->ChannelCreatePutSpace(channel, size); + else + { + size = 0; + return NULLPTR; + } + } + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) + {return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) + {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} + bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} + + unsigned int GetMaxWaitObjectCount() const + { return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; } + void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) + { if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); } + +private: + BufferedTransformation *m_target; + word32 m_behavior; +}; + +/// \brief Filter class that is a proxy for a sink +/// \details Used By ProxyFilter +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation +{ +public: + virtual ~OutputProxy() {} + + /// \brief Construct an OutputProxy + /// \param owner the owning transformation + /// \param passSignal flag indicating if signals should be passed + OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {} + + /// \brief Retrieve passSignal flag + /// \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 + void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} + + byte * CreatePutSpace(size_t &size) + {return m_owner.AttachedTransformation()->CreatePutSpace(size);} + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->Put2(inString, length, m_passSignal ? messageEnd : 0, blocking);} + size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);} + void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) + {if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);} + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;} + bool MessageSeriesEnd(int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;} + + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) + {return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);} + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} + bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} + +private: + BufferedTransformation &m_owner; + bool m_passSignal; +}; + +/// \brief Base class for Filter classes that are proxies for a chain of other filters +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput +{ +public: + virtual ~ProxyFilter() {} + + /// \brief Construct a ProxyFilter + /// \param filter an output filter + /// \param firstSize the first Put size + /// \param lastSize the last Put size + /// \param attachment an attached transformation + ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment); + + bool IsolatedFlush(bool hardFlush, bool blocking); + + /// \brief Sets the OutputProxy filter + /// \param filter an OutputProxy filter + void SetFilter(Filter *filter); + void NextPutMultiple(const byte *s, size_t len); + void NextPutModifiable(byte *inString, size_t length); + +protected: + member_ptr m_filter; +}; + +/// \brief Proxy filter that doesn't modify the underlying filter's input or output +/// \since Crypto++ 5.0 +class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter +{ +public: + /// \brief Construct a SimpleProxyFilter + /// \param filter an output filter + /// \param attachment an attached transformation + SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment) + : ProxyFilter(filter, 0, 0, attachment) {} + + void FirstPut(const byte * inString) + {CRYPTOPP_UNUSED(inString);} + + /// \brief Input the last block of data + /// \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: + ///
+	///     if totalLength < firstSize then length == totalLength
+	///     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
+	///     else lastSize <= length < lastSize+blockSize
+	/// 
+ void LastPut(const byte *inString, size_t length) + {CRYPTOPP_UNUSED(inString), CRYPTOPP_UNUSED(length); m_filter->MessageEnd();} +}; + +/// \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. +/// \since Crypto++ 5.0 +class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter +{ +public: + /// \brief Construct a PK_EncryptorFilter + /// \param rng a RandomNumberGenerator derived class + /// \param encryptor a PK_Encryptor derived class + /// \param attachment an optional attached transformation + PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULLPTR) + : SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {} +}; + +/// \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. +/// \since Crypto++ 5.0 +class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter +{ +public: + /// \brief Construct a PK_DecryptorFilter + /// \param rng a RandomNumberGenerator derived class + /// \param decryptor a PK_Decryptor derived class + /// \param attachment an optional attached transformation + PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULLPTR) + : SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {} +}; + +/// \brief Append input to a string object +/// \tparam T std::basic_string type +/// \details StringSinkTemplate is a StringSinkTemplate typedef +/// \since Crypto++ 5.0 +template +class StringSinkTemplate : public Bufferless +{ +public: + typedef typename T::value_type value_type; + virtual ~StringSinkTemplate() {} + + /// \brief Construct a StringSinkTemplate + /// \param output std::basic_string or std::vector type + StringSinkTemplate(T &output) + : m_output(&output) {CRYPTOPP_ASSERT(sizeof(value_type)==1);} + + void IsolatedInitialize(const NameValuePairs ¶meters) + {if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");} + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); + 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->insert(m_output->end(), (const value_type *)inString, (const value_type *)inString+length); + } + return 0; + } + +private: + T *m_output; +}; + +/// \brief Append input to a string object +/// \details StringSink is a typedef for StringSinkTemplate. +/// \sa ArraySink, ArrayXorSink +/// \since Crypto++ 4.0 +DOCUMENTED_TYPEDEF(StringSinkTemplate, StringSink); +CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate; + +/// \brief Append input to a std::vector object +/// \details VectorSink is a typedef for StringSinkTemplate >. +/// \since Crypto++ 8.0 +DOCUMENTED_TYPEDEF(StringSinkTemplate >, VectorSink); +CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate >; + +/// \brief Incorporates input into RNG as additional entropy +/// \since Crypto++ 4.0 +class RandomNumberSink : public Bufferless +{ +public: + virtual ~RandomNumberSink() {} + + /// \brief Construct a RandomNumberSink + RandomNumberSink() + : m_rng(NULLPTR) {} + + /// \brief Construct a RandomNumberSink + /// \param rng a RandomNumberGenerator derived class + RandomNumberSink(RandomNumberGenerator &rng) + : m_rng(&rng) {} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + +private: + RandomNumberGenerator *m_rng; +}; + +/// \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 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 +{ +public: + virtual ~ArraySink() {} + + /// \brief Construct an ArraySink + /// \param parameters a set of NameValuePairs to initialize this object + /// \details Name::OutputBuffer() is a mandatory parameter using this constructor. + ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) + : m_buf(NULLPTR), m_size(0), m_total(0) {IsolatedInitialize(parameters);} + + /// \brief Construct an ArraySink + /// \param buf pointer to a memory buffer + /// \param size length of the memory buffer + ArraySink(byte *buf, size_t size) + : m_buf(buf), m_size(size), m_total(0) {} + + /// \brief Provides the size remaining in the Sink + /// \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 + /// \return number of bytes written to the Sink, in bytes + lword TotalPutLength() {return m_total;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + byte * CreatePutSpace(size_t &size); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + +protected: + byte *m_buf; + size_t m_size; + lword m_total; +}; + +/// \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 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 +{ +public: + virtual ~ArrayXorSink() {} + + /// \brief Construct an ArrayXorSink + /// \param buf pointer to a memory buffer + /// \param size length of the memory buffer + ArrayXorSink(byte *buf, size_t size) + : ArraySink(buf, size) {} + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);} +}; + +/// \brief String-based implementation of Store interface +/// \since Crypto++ 4.0 +class StringStore : public Store +{ +public: + /// \brief Construct a StringStore + /// \param string pointer to a C-String + StringStore(const char *string = NULLPTR) + {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + + /// \brief Construct a StringStore + /// \param string pointer to a memory buffer + /// \param length size of the memory buffer + StringStore(const byte *string, size_t length) + {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} + + /// \brief Construct a StringStore + /// \tparam T std::basic_string type + /// \param string reference to a std::basic_string type + template StringStore(const T &string) + {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + + CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + +private: + CRYPTOPP_DLL void StoreInitialize(const NameValuePairs ¶meters); + + const byte *m_store; + size_t m_length, m_count; +}; + +/// \brief RNG-based implementation of Source interface +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL RandomNumberStore : public Store +{ +public: + virtual ~RandomNumberStore() {} + + RandomNumberStore() + : m_rng(NULLPTR), m_length(0), m_count(0) {} + + RandomNumberStore(RandomNumberGenerator &rng, lword length) + : m_rng(&rng), m_length(length), m_count(0) {} + + bool AnyRetrievable() const {return MaxRetrievable() != 0;} + lword MaxRetrievable() const {return m_length-m_count;} + + 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 + { + CRYPTOPP_UNUSED(target); CRYPTOPP_UNUSED(begin); CRYPTOPP_UNUSED(end); CRYPTOPP_UNUSED(channel); CRYPTOPP_UNUSED(blocking); + throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store"); + } + +private: + void StoreInitialize(const NameValuePairs ¶meters); + + RandomNumberGenerator *m_rng; + lword m_length, m_count; +}; + +/// \brief Empty store +/// \since Crypto++ 5.0 +class CRYPTOPP_DLL NullStore : public Store +{ +public: + NullStore(lword size = ULONG_MAX) : m_size(size) {} + void StoreInitialize(const NameValuePairs ¶meters) + {CRYPTOPP_UNUSED(parameters);} + lword MaxRetrievable() const {return m_size;} + 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; + +private: + lword m_size; +}; + +/// \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. +/// \details See the discussion of BufferedTransformation in cryptlib.h for +/// more details. +/// \sa Store and SourceTemplate +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting +{ +public: + virtual ~Source() {} + + /// \brief Construct a Source + /// \param attachment an optional attached transformation + Source(BufferedTransformation *attachment = NULLPTR) + {Source::Detach(attachment);} + + /// \name PIPELINE + //@{ + + /// \brief Pump data to attached transformation + /// \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 lword, which is a 64-bit value that typically uses + /// LWORD_MAX. The default argument is SIZE_MAX, 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 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 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 maximum number of bytes to pump + /// \param blocking specifies whether the object should block when processing input + /// \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. + /// \sa Pump, PumpAll, AnyRetrievable, MaxRetrievable + virtual size_t Pump2(lword &byteCount, bool blocking=true) =0; + + /// \brief Pump messages to attached transformation + /// \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 + /// \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 + /// \return true if the source has been exhausted + virtual bool SourceExhausted() const =0; + + //@} + +protected: + void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters) + { + IsolatedInitialize(parameters); + if (pumpAll) + PumpAll(); + } +}; + +/// \brief Transform a Store into a Source +/// \tparam T the class or type +/// \since Crypto++ 5.0 +template +class SourceTemplate : public Source +{ +public: + virtual ~SourceTemplate() {} + + /// \brief Construct a SourceTemplate + /// \param attachment an attached transformation + SourceTemplate(BufferedTransformation *attachment) + : Source(attachment) {} + void IsolatedInitialize(const NameValuePairs ¶meters) + {m_store.IsolatedInitialize(parameters);} + size_t Pump2(lword &byteCount, bool blocking=true) + {return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);} + size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) + {return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);} + size_t PumpAll2(bool blocking=true) + {return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);} + bool SourceExhausted() const + {return !m_store.AnyRetrievable() && !m_store.AnyMessages();} + void SetAutoSignalPropagation(int propagation) + {m_store.SetAutoSignalPropagation(propagation);} + int GetAutoSignalPropagation() const + {return m_store.GetAutoSignalPropagation();} + +protected: + T m_store; +}; + +/// \brief String-based implementation of the Source interface +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL StringSource : public SourceTemplate +{ +public: + /// \brief Construct a StringSource + /// \param attachment an optional attached transformation + StringSource(BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {} + + /// \brief Construct a StringSource + /// \param string C-String + /// \param pumpAll flag indicating if source data should be pumped to its attached transformation + /// \param attachment an optional attached transformation + StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + + /// \brief Construct a StringSource + /// \param string binary byte array + /// \param length size of the byte array + /// \param pumpAll flag indicating if source data should be pumped to its attached transformation + /// \param attachment an optional attached transformation + StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} + + /// \brief Construct a StringSource + /// \param string std::string + /// \param pumpAll flag indicating if source data should be pumped to its attached transformation + /// \param attachment an optional attached transformation + StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} +}; + +/// \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. +/// \since Crypto++ 5.6.0 +DOCUMENTED_TYPEDEF(StringSource, ArraySource); + +/// \brief std::vector-based implementation of the Source interface +/// \since Crypto++ 8.0 +class CRYPTOPP_DLL VectorSource : public SourceTemplate +{ +public: + /// \brief Construct a VectorSource + /// \param attachment an optional attached transformation + VectorSource(BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(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 &vec, bool pumpAll, BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(vec)));} +}; + +/// \brief RNG-based implementation of Source interface +/// \since Crypto++ 4.0 +class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate +{ +public: + RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULLPTR) + : SourceTemplate(attachment) + {SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));} +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/fips140.h b/third_party/cryptoppwin/include/cryptopp/fips140.h new file mode 100644 index 00000000..ebc67edf --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/fips140.h @@ -0,0 +1,112 @@ +// fips140.h - originally written and placed in the public domain by Wei Dai + +/// \file fips140.h +/// \brief Classes and functions for the FIPS 140-2 validated library +/// \details The FIPS validated library is only available on Windows as a DLL. Once compiled, +/// the library is always in FIPS mode contingent upon successful execution of +/// DoPowerUpSelfTest() or DoDllPowerUpSelfTest(). +/// \sa Visual Studio and +/// config.h on the Crypto++ wiki. + +#ifndef CRYPTOPP_FIPS140_H +#define CRYPTOPP_FIPS140_H + +#include "cryptlib.h" +#include "secblock.h" + +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 Algorithm class +/// when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined. +class CRYPTOPP_DLL SelfTestFailure : public Exception +{ +public: + explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {} +}; + +/// \brief Determines whether the library provides FIPS validated cryptography +/// \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 +/// arbitrarily enter or exit the mode. +CRYPTOPP_DLL bool CRYPTOPP_API FIPS_140_2_ComplianceEnabled(); + +/// \brief Status of the power-up self test +enum PowerUpSelfTestStatus { + + /// \brief The self tests have not been performed. + POWER_UP_SELF_TEST_NOT_DONE, + /// \brief The self tests were executed via DoPowerUpSelfTest() or + /// DoDllPowerUpSelfTest(), but the result was failure. + POWER_UP_SELF_TEST_FAILED, + /// \brief The self tests were executed via DoPowerUpSelfTest() or + /// DoDllPowerUpSelfTest(), and the result was success. + POWER_UP_SELF_TEST_PASSED +}; + +/// \brief Performs the power-up self test +/// \param moduleFilename the fully qualified name of the module +/// \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 Algorithm class +/// when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined. +CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac); + +/// \brief Performs the power-up self test on the DLL +/// \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 Algorithm class +/// when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined. +CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest(); + +/// \brief Sets the power-up self test status to POWER_UP_SELF_TEST_FAILED +/// \details Sets the power-up self test status to POWER_UP_SELF_TEST_FAILED to simulate failure. +CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure(); + +/// \brief Provides 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 +typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)(); +#endif + +/// \brief Class object that calculates the MAC on 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 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 +// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test +bool PowerUpSelfTestInProgressOnThisThread(); + +void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress); + +void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier); +void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor); + +void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier); +void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor); +#endif + +/// \brief The placeholder used prior to embedding the actual MAC in the module. +/// \details After the DLL is built but before it is MAC'd, the string CRYPTOPP_DUMMY_DLL_MAC +/// is used as a placeholder for the actual MAC. A post-build step is performed which calculates +/// the MAC of the DLL and embeds it in the module. The actual MAC is written by the +/// cryptest.exe program using the mac_dll subcommand. +#define CRYPTOPP_DUMMY_DLL_MAC "MAC_51f34b8db820ae8" + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/fltrimpl.h b/third_party/cryptoppwin/include/cryptopp/fltrimpl.h new file mode 100644 index 00000000..399a7292 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/fltrimpl.h @@ -0,0 +1,69 @@ +#ifndef CRYPTOPP_FLTRIMPL_H +#define CRYPTOPP_FLTRIMPL_H + +#define FILTER_BEGIN \ + switch (m_continueAt) \ + { \ + case 0: \ + m_inputPosition = 0; + +#define FILTER_END_NO_MESSAGE_END_NO_RETURN \ + break; \ + default: \ + CRYPTOPP_ASSERT(false); \ + } + +#define FILTER_END_NO_MESSAGE_END \ + FILTER_END_NO_MESSAGE_END_NO_RETURN \ + return 0; + +/* +#define FILTER_END \ + case -1: \ + if (messageEnd && Output(-1, NULLPTR, 0, messageEnd, blocking)) \ + return 1; \ + FILTER_END_NO_MESSAGE_END +*/ + +#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \ + {\ + case site: \ + (void) statement; \ + if (Output(site, output, length, messageEnd, blocking, channel)) \ + return STDMAX(size_t(1), length-m_inputPosition);\ + } + +#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \ + FILTER_OUTPUT3(site, statement, output, length, messageEnd, DEFAULT_CHANNEL) + +#define FILTER_OUTPUT(site, output, length, messageEnd) \ + FILTER_OUTPUT2(site, 0, output, length, messageEnd) + +#define FILTER_OUTPUT_BYTE(site, output) \ + FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0) + +#define FILTER_OUTPUT2_MODIFIABLE(site, statement, output, length, messageEnd) \ + {\ + /* fall through */ \ + case site: \ + (void) statement; \ + if (OutputModifiable(site, output, length, messageEnd, blocking)) \ + return STDMAX(size_t(1), length-m_inputPosition);\ + } + +#define FILTER_OUTPUT_MODIFIABLE(site, output, length, messageEnd) \ + FILTER_OUTPUT2_MODIFIABLE(site, 0, output, length, messageEnd) + +#define FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, statement, output, length, messageEnd, modifiable) \ + {\ + /* fall through */ \ + case site: \ + (void) statement; \ + if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking)) \ + return STDMAX(size_t(1), length-m_inputPosition);\ + } + +#define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable) \ + FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable) + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/gcm.h b/third_party/cryptoppwin/include/cryptopp/gcm.h new file mode 100644 index 00000000..0f4d7025 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/gcm.h @@ -0,0 +1,139 @@ +// gcm.h - originally written and placed in the public domain by Wei Dai + +/// \file gcm.h +/// \brief GCM block cipher mode of operation +/// \since Crypto++ 5.6.0 + +#ifndef CRYPTOPP_GCM_H +#define CRYPTOPP_GCM_H + +#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 +/// \brief GCM table size options +enum GCM_TablesOption { + /// \brief Use a table with 2K entries + GCM_2K_Tables, + /// \brief Use a table with 64K entries + GCM_64K_Tables}; + +/// \brief GCM block cipher base implementation +/// \details Base implementation of the AuthenticatedSymmetricCipher interface +/// \since Crypto++ 5.6.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase +{ +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 + {return GetBlockCipher().MaxKeyLength();} + size_t DefaultKeyLength() const + {return GetBlockCipher().DefaultKeyLength();} + size_t GetValidKeyLength(size_t n) const + {return GetBlockCipher().GetValidKeyLength(n);} + bool IsValidKeyLength(size_t n) const + {return GetBlockCipher().IsValidKeyLength(n);} + unsigned int OptimalDataAlignment() const; + IV_Requirement IVRequirement() const + {return UNIQUE_IV;} + unsigned int IVSize() const + {return 12;} + unsigned int MinIVLength() const + {return 1;} + unsigned int MaxIVLength() const + {return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard + unsigned int DigestSize() const + {return 16;} + lword MaxHeaderLength() const + {return (W64LIT(1)<<61)-1;} + lword MaxMessageLength() const + {return ((W64LIT(1)<<39)-256)/8;} + +protected: + // AuthenticatedSymmetricCipherBase + bool AuthenticationIsOnPlaintext() const + {return false;} + unsigned int AuthenticationBlockSize() const + {return HASH_BLOCKSIZE;} + void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + 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); + SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} + + virtual BlockCipher & AccessBlockCipher() =0; + virtual GCM_TablesOption GetTablesOption() const =0; + + const BlockCipher & GetBlockCipher() const {return const_cast(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;} + inline void ReverseHashBufferIfNeeded(); + + class CRYPTOPP_DLL GCTR : public CTR_Mode_ExternalCipher::Encryption + { + protected: + void IncrementCounterBy256(); + }; + + GCTR m_ctr; + static word16 s_reductionTable[256]; + static volatile bool s_reductionTableInitialized; + enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16}; +}; + +/// \brief GCM block cipher final implementation +/// \tparam T_BlockCipher block cipher +/// \tparam T_TablesOption table size, either \p GCM_2K_Tables or \p GCM_64K_Tables +/// \tparam T_IsEncryption direction in which to operate the cipher +/// \since Crypto++ 5.6.0 +template +class GCM_Final : public GCM_Base +{ +public: + static std::string StaticAlgorithmName() + {return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");} + bool IsForwardTransformation() const + {return T_IsEncryption;} + +private: + GCM_TablesOption GetTablesOption() const {return T_TablesOption;} + BlockCipher & AccessBlockCipher() {return m_cipher;} + typename T_BlockCipher::Encryption m_cipher; +}; + +/// \brief GCM block cipher mode of operation +/// \tparam T_BlockCipher block cipher +/// \tparam T_TablesOption table size, either \p GCM_2K_Tables or \p GCM_64K_Tables +/// \details \p GCM provides the \p Encryption and \p Decryption typedef. See GCM_Base +/// and GCM_Final for the AuthenticatedSymmetricCipher implementation. +/// \sa GCM Mode and +/// Modes of Operation +/// on the Crypto++ wiki. +/// \since Crypto++ 5.6.0 +template +struct GCM : public AuthenticatedSymmetricCipherDocumentation +{ + typedef GCM_Final Encryption; + typedef GCM_Final Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/gf256.h b/third_party/cryptoppwin/include/cryptopp/gf256.h new file mode 100644 index 00000000..3c5c3f61 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/gf256.h @@ -0,0 +1,72 @@ +// gf256.h - originally written and placed in the public domain by Wei Dai + +/// \file gf256.h +/// \brief Classes and functions for schemes over GF(256) + +#ifndef CRYPTOPP_GF256_H +#define CRYPTOPP_GF256_H + +#include "cryptlib.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief GF(256) with polynomial basis +class GF256 +{ +public: + typedef byte Element; + typedef int RandomizationParameter; + + GF256(byte modulus) : m_modulus(modulus) {} + + Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const + {CRYPTOPP_UNUSED(ignored); return rng.GenerateByte();} + + bool Equal(Element a, Element b) const + {return a==b;} + + Element Zero() const + {return 0;} + + Element Add(Element a, Element b) const + {return a^b;} + + Element& Accumulate(Element &a, Element b) const + {return a^=b;} + + Element Inverse(Element a) const + {return a;} + + Element Subtract(Element a, Element b) const + {return a^b;} + + Element& Reduce(Element &a, Element b) const + {return a^=b;} + + Element Double(Element a) const + {CRYPTOPP_UNUSED(a); return 0;} + + Element One() const + {return 1;} + + Element Multiply(Element a, Element b) const; + + Element Square(Element a) const + {return Multiply(a, a);} + + bool IsUnit(Element a) const + {return a != 0;} + + Element MultiplicativeInverse(Element a) const; + + Element Divide(Element a, Element b) const + {return Multiply(a, MultiplicativeInverse(b));} + +private: + word m_modulus; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/gf2_32.h b/third_party/cryptoppwin/include/cryptopp/gf2_32.h new file mode 100644 index 00000000..9e794fe7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/gf2_32.h @@ -0,0 +1,73 @@ +// gf2_32.h - originally written and placed in the public domain by Wei Dai + +/// \file gf2_32.h +/// \brief Classes and functions for schemes over GF(2^32) + +#ifndef CRYPTOPP_GF2_32_H +#define CRYPTOPP_GF2_32_H + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief GF(2^32) with polynomial basis +class GF2_32 +{ +public: + typedef word32 Element; + typedef int RandomizationParameter; + + GF2_32(word32 modulus=0x0000008D) : m_modulus(modulus) {} + + Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const + {CRYPTOPP_UNUSED(ignored); return rng.GenerateWord32();} + + bool Equal(Element a, Element b) const + {return a==b;} + + Element Identity() const + {return 0;} + + Element Add(Element a, Element b) const + {return a^b;} + + Element& Accumulate(Element &a, Element b) const + {return a^=b;} + + Element Inverse(Element a) const + {return a;} + + Element Subtract(Element a, Element b) const + {return a^b;} + + Element& Reduce(Element &a, Element b) const + {return a^=b;} + + Element Double(Element a) const + {CRYPTOPP_UNUSED(a); return 0;} + + Element MultiplicativeIdentity() const + {return 1;} + + Element Multiply(Element a, Element b) const; + + Element Square(Element a) const + {return Multiply(a, a);} + + bool IsUnit(Element a) const + {return a != 0;} + + Element MultiplicativeInverse(Element a) const; + + Element Divide(Element a, Element b) const + {return Multiply(a, MultiplicativeInverse(b));} + +private: + word32 m_modulus; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/gf2n.h b/third_party/cryptoppwin/include/cryptopp/gf2n.h new file mode 100644 index 00000000..4b61fb88 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/gf2n.h @@ -0,0 +1,406 @@ +// gf2n.h - originally written and placed in the public domain by Wei Dai + +/// \file gf2n.h +/// \brief Classes and functions for schemes over GF(2^n) + +#ifndef CRYPTOPP_GF2N_H +#define CRYPTOPP_GF2N_H + +#include "cryptlib.h" +#include "secblock.h" +#include "algebra.h" +#include "misc.h" +#include "asn.h" + +#include + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Polynomial with Coefficients in GF(2) +/*! \nosubgrouping */ +class CRYPTOPP_DLL PolynomialMod2 +{ +public: + /// \name ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + /// \brief Exception thrown when divide by zero is encountered + class DivideByZero : public Exception + { + public: + DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {} + }; + + typedef unsigned int RandomizationParameter; + //@} + + /// \name CREATORS + //@{ + /// \brief Construct the zero polynomial + PolynomialMod2(); + /// Copy construct a PolynomialMod2 + PolynomialMod2(const PolynomialMod2& t); + + /// \brief Construct a PolynomialMod2 from a word + /// \details value should be encoded with the least significant bit as coefficient to x^0 + /// and most significant bit as coefficient to x^(WORD_BITS-1) + /// bitLength denotes how much memory to allocate initially + PolynomialMod2(word value, size_t bitLength=WORD_BITS); + + /// \brief Construct a PolynomialMod2 from big-endian byte array + PolynomialMod2(const byte *encodedPoly, size_t byteCount) + {Decode(encodedPoly, byteCount);} + + /// \brief Construct a PolynomialMod2 from big-endian form stored in a BufferedTransformation + PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount) + {Decode(encodedPoly, byteCount);} + + /// \brief Create a uniformly distributed random polynomial + /// \details Create a random polynomial uniformly distributed over all polynomials with degree less than bitcount + PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount) + {Randomize(rng, bitcount);} + + /// \brief Provides x^i + /// \return x^i + static PolynomialMod2 CRYPTOPP_API Monomial(size_t i); + /// \brief Provides x^t0 + x^t1 + x^t2 + /// \return x^t0 + x^t1 + x^t2 + /// \pre The coefficients should be provided in descending order. That is,
t0 > t1 > 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
+		/// \return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
+		/// \pre The coefficients should be provided in descending order. That is, 
t0 > t1 > t2 > t3 > 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
+		/// \return x^(n-1) + ... + x + 1
+		static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n);
+
+		/// \brief The Zero polinomial
+		/// \return the zero polynomial
+		static const PolynomialMod2 & CRYPTOPP_API Zero();
+		/// \brief The One polinomial
+		/// \return the one polynomial
+		static const PolynomialMod2 & CRYPTOPP_API One();
+	//@}
+
+	/// \name ENCODE/DECODE
+	//@{
+		/// minimum number of bytes to encode this polynomial
+		/*! MinEncodedSize of 0 is 1 */
+		unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());}
+
+		/// encode in big-endian format
+		/// \details if outputLen < MinEncodedSize, the most significant bytes will be dropped
+		///   if outputLen > MinEncodedSize, the most significant bytes will be padded
+		void Encode(byte *output, size_t outputLen) const;
+		///
+		void Encode(BufferedTransformation &bt, size_t outputLen) const;
+
+		///
+		void Decode(const byte *input, size_t inputLen);
+		///
+		//* Precondition: bt.MaxRetrievable() >= inputLen
+		void Decode(BufferedTransformation &bt, size_t inputLen);
+
+		/// encode value as big-endian octet string
+		void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
+		/// decode value as big-endian octet string
+		void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
+	//@}
+
+	/// \name ACCESSORS
+	//@{
+		/// number of significant bits = Degree() + 1
+		unsigned int BitCount() const;
+		/// number of significant bytes = ceiling(BitCount()/8)
+		unsigned int ByteCount() const;
+		/// number of significant words = ceiling(ByteCount()/sizeof(word))
+		unsigned int WordCount() const;
+
+		/// return the n-th bit, n=0 being the least significant bit
+		bool GetBit(size_t n) const {return GetCoefficient(n)!=0;}
+		/// return the n-th byte
+		byte GetByte(size_t n) const;
+
+		/// the zero polynomial will return a degree of -1
+		signed int Degree() const {return (signed int)(BitCount()-1U);}
+		/// degree + 1
+		unsigned int CoefficientCount() const {return BitCount();}
+		/// return coefficient for x^i
+		int GetCoefficient(size_t i) const
+			{return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;}
+		/// return coefficient for x^i
+		int operator[](unsigned int i) const {return GetCoefficient(i);}
+
+		///
+		bool IsZero() const {return !*this;}
+		///
+		bool Equals(const PolynomialMod2 &rhs) const;
+	//@}
+
+	/// \name MANIPULATORS
+	//@{
+		///
+		PolynomialMod2&  operator=(const PolynomialMod2& t);
+		///
+		PolynomialMod2&  operator&=(const PolynomialMod2& t);
+		///
+		PolynomialMod2&  operator^=(const PolynomialMod2& t);
+		///
+		PolynomialMod2&  operator+=(const PolynomialMod2& t) {return *this ^= t;}
+		///
+		PolynomialMod2&  operator-=(const PolynomialMod2& t) {return *this ^= t;}
+		///
+		PolynomialMod2&  operator*=(const PolynomialMod2& t);
+		///
+		PolynomialMod2&  operator/=(const PolynomialMod2& t);
+		///
+		PolynomialMod2&  operator%=(const PolynomialMod2& t);
+		///
+		PolynomialMod2&  operator<<=(unsigned int);
+		///
+		PolynomialMod2&  operator>>=(unsigned int);
+
+		///
+		void Randomize(RandomNumberGenerator &rng, size_t bitcount);
+
+		///
+		void SetBit(size_t i, int value = 1);
+		/// set the n-th byte to value
+		void SetByte(size_t n, byte value);
+
+		///
+		void SetCoefficient(size_t i, int value) {SetBit(i, value);}
+
+		///
+		void swap(PolynomialMod2 &a) {reg.swap(a.reg);}
+	//@}
+
+	/// \name UNARY OPERATORS
+	//@{
+		///
+		bool			operator!() const;
+		///
+		PolynomialMod2	operator+() const {return *this;}
+		///
+		PolynomialMod2	operator-() const {return *this;}
+	//@}
+
+	/// \name BINARY OPERATORS
+	//@{
+		///
+		PolynomialMod2 And(const PolynomialMod2 &b) const;
+		///
+		PolynomialMod2 Xor(const PolynomialMod2 &b) const;
+		///
+		PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);}
+		///
+		PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);}
+		///
+		PolynomialMod2 Times(const PolynomialMod2 &b) const;
+		///
+		PolynomialMod2 DividedBy(const PolynomialMod2 &b) const;
+		///
+		PolynomialMod2 Modulo(const PolynomialMod2 &b) const;
+
+		///
+		PolynomialMod2 operator>>(unsigned int n) const;
+		///
+		PolynomialMod2 operator<<(unsigned int n) const;
+	//@}
+
+	/// \name OTHER ARITHMETIC FUNCTIONS
+	//@{
+		/// sum modulo 2 of all coefficients
+		unsigned int Parity() const;
+
+		/// check for irreducibility
+		bool IsIrreducible() const;
+
+		/// is always zero since we're working modulo 2
+		PolynomialMod2 Doubled() const {return Zero();}
+		///
+		PolynomialMod2 Squared() const;
+
+		/// only 1 is a unit
+		bool IsUnit() const {return Equals(One());}
+		/// return inverse if *this is a unit, otherwise return 0
+		PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();}
+
+		/// greatest common divisor
+		static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n);
+		/// calculate multiplicative inverse of *this mod n
+		PolynomialMod2 InverseMod(const PolynomialMod2 &) const;
+
+		/// calculate r and q such that (a == d*q + r) && (deg(r) < deg(d))
+		static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d);
+	//@}
+
+	/// \name INPUT/OUTPUT
+	//@{
+		///
+		friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a);
+	//@}
+
+private:
+	friend class GF2NT;
+	friend class GF2NT233;
+
+	SecWordBlock reg;
+};
+
+///
+inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Equals(b);}
+///
+inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return !(a==b);}
+/// compares degree
+inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() > b.Degree();}
+/// compares degree
+inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() >= b.Degree();}
+/// compares degree
+inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() < b.Degree();}
+/// compares degree
+inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() <= b.Degree();}
+///
+inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);}
+///
+inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);}
+///
+inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);}
+///
+inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);}
+///
+inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);}
+///
+inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);}
+///
+inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);}
+
+// CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations,
+// but before the use of QuotientRing > for VC .NET 2003
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain;
+CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf;
+CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing >;
+
+/// \brief GF(2^n) with Polynomial Basis
+class CRYPTOPP_DLL GF2NP : public QuotientRing >
+{
+public:
+	GF2NP(const PolynomialMod2 &modulus);
+
+	virtual GF2NP * Clone() const {return new GF2NP(*this);}
+	virtual void DEREncode(BufferedTransformation &bt) const
+		{CRYPTOPP_UNUSED(bt); CRYPTOPP_ASSERT(false);}	// no ASN.1 syntax yet for general polynomial basis
+
+	void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
+	void BERDecodeElement(BufferedTransformation &in, Element &a) const;
+
+	bool Equal(const Element &a, const Element &b) const
+		{CRYPTOPP_ASSERT(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);}
+
+	bool IsUnit(const Element &a) const
+		{CRYPTOPP_ASSERT(a.Degree() < m_modulus.Degree()); return !!a;}
+
+	unsigned int MaxElementBitLength() const
+		{return m;}
+
+	unsigned int MaxElementByteLength() const
+		{return (unsigned int)BitsToBytes(MaxElementBitLength());}
+
+	Element SquareRoot(const Element &a) const;
+
+	Element HalfTrace(const Element &a) const;
+
+	// returns z such that z^2 + z == a
+	Element SolveQuadraticEquation(const Element &a) const;
+
+protected:
+	unsigned int m;
+};
+
+/// \brief GF(2^n) with Trinomial Basis
+class CRYPTOPP_DLL GF2NT : public GF2NP
+{
+public:
+	// polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
+	GF2NT(unsigned int t0, unsigned int t1, unsigned int t2);
+
+	GF2NP * Clone() const {return new GF2NT(*this);}
+	void DEREncode(BufferedTransformation &bt) const;
+
+	const Element& Multiply(const Element &a, const Element &b) const;
+
+	const Element& Square(const Element &a) const
+		{return Reduced(a.Squared());}
+
+	const Element& MultiplicativeInverse(const Element &a) const;
+
+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)), t1(t1), t2(t2), t3(t3) {}
+
+	GF2NP * Clone() const {return new GF2NPP(*this);}
+	void DEREncode(BufferedTransformation &bt) const;
+
+private:
+	unsigned int t1, t2, t3;
+};
+
+// construct new GF2NP from the ASN.1 sequence Characteristic-two
+CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt);
+
+NAMESPACE_END
+
+#ifndef __BORLANDC__
+NAMESPACE_BEGIN(std)
+template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b)
+{
+	a.swap(b);
+}
+NAMESPACE_END
+#endif
+
+#if CRYPTOPP_MSC_VERSION
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/third_party/cryptoppwin/include/cryptopp/gfpcrypt.h b/third_party/cryptoppwin/include/cryptopp/gfpcrypt.h
new file mode 100644
index 00000000..741ee477
--- /dev/null
+++ b/third_party/cryptoppwin/include/cryptopp/gfpcrypt.h
@@ -0,0 +1,1036 @@
+// gfpcrypt.h - originally written and placed in the public domain by Wei Dai
+//              RFC6979 deterministic signatures added by Douglas Roark
+//              ECGDSA added by Jeffrey Walton
+
+/// \file gfpcrypt.h
+/// \brief Classes and functions for schemes based on Discrete Logs (DL) over GF(p)
+
+#ifndef CRYPTOPP_GFPCRYPT_H
+#define CRYPTOPP_GFPCRYPT_H
+
+#include "config.h"
+
+#if CRYPTOPP_MSC_VERSION
+# pragma warning(push)
+# pragma warning(disable: 4189 4231 4275)
+#endif
+
+#include "cryptlib.h"
+#include "pubkey.h"
+#include "integer.h"
+#include "modexppc.h"
+#include "algparam.h"
+#include "smartptr.h"
+#include "sha.h"
+#include "asn.h"
+#include "hmac.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters;
+
+/// \brief Integer-based GroupParameters specialization
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial >
+{
+    typedef DL_GroupParameters_IntegerBased ThisClass;
+
+public:
+    virtual ~DL_GroupParameters_IntegerBased() {}
+
+    /// \brief Initialize a group parameters over integers
+    /// \param params the group parameters
+    void Initialize(const DL_GroupParameters_IntegerBased ¶ms)
+        {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
+
+    /// \brief Create a group parameters over integers
+    /// \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.
+    void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
+        {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
+
+    /// \brief Initialize a group parameters over integers
+    /// \param p the modulus
+    /// \param g the generator
+    void Initialize(const Integer &p, const Integer &g)
+        {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
+
+    /// \brief Initialize a group parameters over integers
+    /// \param p the modulus
+    /// \param q the subgroup order
+    /// \param g the generator
+    void Initialize(const Integer &p, const Integer &q, const Integer &g)
+        {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
+
+    // ASN1Object interface
+    void BERDecode(BufferedTransformation &bt);
+    void DEREncode(BufferedTransformation &bt) const;
+
+    /// \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
+    const Integer & GetSubgroupOrder() const {return m_q;}
+    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 *precomp) const;
+
+    /// \brief Determine if subgroup membership check is fast
+    /// \return true or false
+    bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
+
+    /// \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 COUNTOF(encoded) == GetEncodedElementSize()
+    /// \sa GetEncodedElementSize(), DecodeElement(), Cygwin
+    ///  i386 crash at -O3
+    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 COUNTOF(encoded) == GetEncodedElementSize()
+    /// \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;
+
+    /// \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);}
+
+    // GF(p) = 1, GF(p^2) = 2
+    virtual int GetFieldType() const =0;
+    virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
+
+private:
+    Integer m_q;
+};
+
+/// \brief Integer-based GroupParameters default implementation
+/// \tparam GROUP_PRECOMP group parameters precomputation specialization
+/// \tparam BASE_PRECOMP base class precomputation specialization
+template  >
+class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl
+{
+    typedef DL_GroupParameters_IntegerBasedImpl ThisClass;
+
+public:
+    typedef typename GROUP_PRECOMP::Element Element;
+
+    virtual ~DL_GroupParameters_IntegerBasedImpl() {}
+
+    // GeneratibleCryptoMaterial interface
+    bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+        {return GetValueHelper(this, name, valueType, pValue).Assignable();}
+
+    void AssignFrom(const NameValuePairs &source)
+        {AssignFromHelper(this, source);}
+
+    // DL_GroupParameters
+    const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;}
+    DL_FixedBasePrecomputation & 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
+        {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
+
+    // non-inherited
+    bool operator==(const DL_GroupParameters_IntegerBasedImpl &rhs) const
+        {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
+    bool operator!=(const DL_GroupParameters_IntegerBasedImpl &rhs) const
+        {return !operator==(rhs);}
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl;
+
+/// \brief GF(p) group parameters
+class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl
+{
+public:
+    virtual ~DL_GroupParameters_GFP() {}
+
+    /// \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 COUNTOF(results) == exponentsCount
+    /// \pre COUNTOF(exponents) == exponentsCount
+    void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+
+    /// \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(this, name, valueType, pValue).Assignable();
+    }
+
+    // used by MQV
+    Element MultiplyElements(const Element &a, const Element &b) const;
+    Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
+
+protected:
+    int GetFieldType() const {return 1;}
+};
+
+/// \brief GF(p) group parameters that default to safe primes
+class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
+{
+public:
+    typedef NoCofactorMultiplication DefaultCofactorOption;
+
+    virtual ~DL_GroupParameters_GFP_DefaultSafePrime() {}
+
+protected:
+    unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
+};
+
+/// ElGamal encryption for safe interop
+/// \sa On the
+///  (in)security of ElGamal in OpenPGP,
+///  Issue 1059,
+///  CVE-2021-40530
+/// \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 T can be Integer, ECP or EC2N.
+template 
+class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm
+{
+public:
+    CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
+
+    virtual ~DL_Algorithm_GDSA() {}
+
+    void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
+    {
+        const Integer &q = params.GetSubgroupOrder();
+        r %= q;
+        Integer kInv = k.InverseMod(q);
+        s = (kInv * (x*r + e)) % q;
+        CRYPTOPP_ASSERT(!!r && !!s);
+    }
+
+    bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const
+    {
+        const Integer &q = params.GetSubgroupOrder();
+        if (r>=q || r<1 || s>=q || s<1)
+            return false;
+
+        Integer w = s.InverseMod(q);
+        Integer u1 = (e * w) % q;
+        Integer u2 = (r * w) % q;
+        // verify r == (g^u1 * y^u2 mod p) mod q
+        return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
+    }
+};
+
+/// \brief DSA signature algorithm based on RFC 6979
+/// \tparam T FieldElement type or class
+/// \tparam H HashTransformation derived class
+/// \details FieldElement T can be Integer, ECP or EC2N.
+/// \sa RFC 6979, Deterministic Usage of the
+///  Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)
+/// \since Crypto++ 6.0
+template 
+class DL_Algorithm_DSA_RFC6979 : public DL_Algorithm_GDSA, public DeterministicSignatureAlgorithm
+{
+public:
+    CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "DSA-RFC6979";}
+
+    virtual ~DL_Algorithm_DSA_RFC6979() {}
+
+    bool IsProbabilistic() const
+        {return false;}
+    bool IsDeterministic() const
+        {return true;}
+
+    // Deterministic K
+    Integer GenerateRandom(const Integer &x, const Integer &q, const Integer &e) const
+    {
+        static const byte zero = 0, one = 1;
+        const size_t qlen = q.BitCount();
+        const size_t rlen = BitsToBytes(qlen);
+
+        // Step (a) - formatted E(m)
+        SecByteBlock BH(e.MinEncodedSize());
+        e.Encode(BH, BH.size());
+        BH = bits2octets(BH, q);
+
+        // Step (a) - private key to byte array
+        SecByteBlock BX(STDMAX(rlen, x.MinEncodedSize()));
+        x.Encode(BX, BX.size());
+
+        // Step (b)
+        SecByteBlock V(H::DIGESTSIZE);
+        std::fill(V.begin(), V.begin()+H::DIGESTSIZE, one);
+
+        // Step (c)
+        SecByteBlock K(H::DIGESTSIZE);
+        std::fill(K.begin(), K.begin()+H::DIGESTSIZE, zero);
+
+        // Step (d)
+        m_hmac.SetKey(K, K.size());
+        m_hmac.Update(V, V.size());
+        m_hmac.Update(&zero, 1);
+        m_hmac.Update(BX, BX.size());
+        m_hmac.Update(BH, BH.size());
+        m_hmac.TruncatedFinal(K, K.size());
+
+        // Step (e)
+        m_hmac.SetKey(K, K.size());
+        m_hmac.Update(V, V.size());
+        m_hmac.TruncatedFinal(V, V.size());
+
+        // Step (f)
+        m_hmac.SetKey(K, K.size());
+        m_hmac.Update(V, V.size());
+        m_hmac.Update(&one, 1);
+        m_hmac.Update(BX, BX.size());
+        m_hmac.Update(BH, BH.size());
+        m_hmac.TruncatedFinal(K, K.size());
+
+        // Step (g)
+        m_hmac.SetKey(K, K.size());
+        m_hmac.Update(V, V.size());
+        m_hmac.TruncatedFinal(V, V.size());
+
+        Integer k;
+        SecByteBlock temp(rlen);
+        for (;;)
+        {
+            // We want qlen bits, but we support only hash functions with an output length
+            //   multiple of 8; hence, we will gather rlen bits, i.e., rolen octets.
+            size_t toff = 0;
+            while (toff < rlen)
+            {
+                m_hmac.Update(V, V.size());
+                m_hmac.TruncatedFinal(V, V.size());
+
+                size_t cc = STDMIN(V.size(), temp.size() - toff);
+                memcpy_s(temp+toff, temp.size() - toff, V, cc);
+                toff += cc;
+            }
+
+            k = bits2int(temp, qlen);
+            if (k > 0 && k < q)
+                break;
+
+            // k is not in the proper range; update K and V, and loop.
+            m_hmac.Update(V, V.size());
+            m_hmac.Update(&zero, 1);
+            m_hmac.TruncatedFinal(K, K.size());
+
+            m_hmac.SetKey(K, K.size());
+            m_hmac.Update(V, V.size());
+            m_hmac.TruncatedFinal(V, V.size());
+        }
+
+        return k;
+    }
+
+protected:
+
+    Integer bits2int(const SecByteBlock& bits, size_t qlen) const
+    {
+        Integer ret(bits, bits.size());
+        size_t blen = bits.size()*8;
+
+        if (blen > qlen)
+            ret >>= blen - qlen;
+
+        return ret;
+    }
+
+    // RFC 6979 support function. Takes an integer and converts it into bytes that
+    // are the same length as an elliptic curve's order.
+    SecByteBlock int2octets(const Integer& val, size_t rlen) const
+    {
+        SecByteBlock block(val.MinEncodedSize());
+        val.Encode(block, val.MinEncodedSize());
+
+        if (block.size() == rlen)
+            return block;
+
+        // The least significant bytes are the ones we need to preserve.
+        SecByteBlock t(rlen);
+        if (block.size() > rlen)
+        {
+            size_t offset = block.size() - rlen;
+            std::memcpy(t, block + offset, rlen);
+        }
+        else // block.size() < rlen
+        {
+            size_t offset = rlen - block.size();
+            std::memset(t, '\x00', offset);
+            std::memcpy(t + offset, block, rlen - offset);
+        }
+
+        return t;
+    }
+
+    // Turn a stream of bits into a set of bytes with the same length as an elliptic
+    // curve's order.
+    SecByteBlock bits2octets(const SecByteBlock& in, const Integer& q) const
+    {
+        Integer b2 = bits2int(in, q.BitCount());
+        Integer b1 = b2 - q;
+        return int2octets(b1.IsNegative() ? b2 : b1, q.ByteCount());
+    }
+
+private:
+    mutable H m_hash;
+    mutable HMAC m_hmac;
+};
+
+/// \brief German Digital Signature Algorithm
+/// \tparam T FieldElement type or class
+/// \details FieldElement T 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 gfpcrypt.h.
+/// \sa Erwin Hess, Marcus Schafheutle, and Pascale Serf 
+///  The Digital Signature Scheme ECGDSA (October 24, 2006)
+template 
+class DL_Algorithm_GDSA_ISO15946 : public DL_ElgamalLikeSignatureAlgorithm
+{
+public:
+    CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "GDSA-ISO15946";}
+
+    virtual ~DL_Algorithm_GDSA_ISO15946() {}
+
+    void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
+    {
+        const Integer &q = params.GetSubgroupOrder();
+        // r = x(k * G) mod q
+        r = params.ConvertElementToInteger(params.ExponentiateBase(k)) % q;
+        // s = (k * r - h(m)) * d_A mod q
+        s = (k * r - e) * x % q;
+        CRYPTOPP_ASSERT(!!r && !!s);
+    }
+
+    bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const
+    {
+        const Integer &q = params.GetSubgroupOrder();
+        if (r>=q || r<1 || s>=q || s<1)
+            return false;
+
+        const Integer& rInv = r.InverseMod(q);
+        const Integer u1 = (rInv * e) % q;
+        const Integer u2 = (rInv * s) % q;
+        // verify x(G^u1 + P_A^u2) mod q
+        return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
+    }
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_DSA_RFC6979;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_DSA_RFC6979;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_DSA_RFC6979;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_DSA_RFC6979;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_DSA_RFC6979;
+
+/// \brief NR algorithm
+/// \tparam T FieldElement type or class
+/// \details FieldElement T can be Integer, ECP or EC2N.
+template 
+class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm
+{
+public:
+    CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "NR";}
+
+    virtual ~DL_Algorithm_NR() {}
+
+    void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
+    {
+        const Integer &q = params.GetSubgroupOrder();
+        r = (r + e) % q;
+        s = (k - x*r) % q;
+        CRYPTOPP_ASSERT(!!r);
+    }
+
+    bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const
+    {
+        const Integer &q = params.GetSubgroupOrder();
+        if (r>=q || r<1 || s>=q)
+            return false;
+
+        // check r == (m_g^s * m_y^r + m) mod m_q
+        return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
+    }
+};
+
+/// \brief Discrete Log (DL) public key in GF(p) groups
+/// \tparam GP GroupParameters derived class
+/// \details DSA public key format is defined in 7.3.3 of RFC 2459. The    private key format is defined in 12.9 of PKCS #11 v2.10.
+template 
+class DL_PublicKey_GFP : public DL_PublicKeyImpl
+{
+public:
+    virtual ~DL_PublicKey_GFP() {}
+
+    /// \brief Initialize a public key over GF(p)
+    /// \param params the group parameters
+    /// \param y the public element
+    void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &y)
+        {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
+
+    /// \brief Initialize a public key over GF(p)
+    /// \param p the modulus
+    /// \param g the generator
+    /// \param y the public element
+    void Initialize(const Integer &p, const Integer &g, const Integer &y)
+        {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
+
+    /// \brief Initialize a public key over GF(p)
+    /// \param p the modulus
+    /// \param q the subgroup order
+    /// \param g the generator
+    /// \param y the public element
+    void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
+        {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
+
+    // X509PublicKey
+    void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
+        {this->SetPublicElement(Integer(bt));}
+    void DEREncodePublicKey(BufferedTransformation &bt) const
+        {this->GetPublicElement().DEREncode(bt);}
+};
+
+/// \brief Discrete Log (DL) private key in GF(p) groups
+/// \tparam GP GroupParameters derived class
+template 
+class DL_PrivateKey_GFP : public DL_PrivateKeyImpl
+{
+public:
+    virtual ~DL_PrivateKey_GFP();
+
+    /// \brief Create a private key
+    /// \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.
+    void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
+        {this->GenerateRandomWithKeySize(rng, modulusBits);}
+
+    /// \brief Create a private key
+    /// \param rng a RandomNumberGenerator derived class
+    /// \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.
+    void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
+        {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
+
+    /// \brief Create a private key
+    /// \param rng a RandomNumberGenerator derived class
+    /// \param p the modulus
+    /// \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.
+    void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
+        {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
+
+    /// \brief Initialize a private key over GF(p)
+    /// \param params the group parameters
+    /// \param x the private exponent
+    void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &x)
+        {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
+
+    /// \brief Initialize a private key over GF(p)
+    /// \param p the modulus
+    /// \param g the generator
+    /// \param x the private exponent
+    void Initialize(const Integer &p, const Integer &g, const Integer &x)
+        {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
+
+    /// \brief Initialize a private key over GF(p)
+    /// \param p the modulus
+    /// \param q the subgroup order
+    /// \param g the generator
+    /// \param x the private exponent
+    void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
+        {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
+};
+
+// Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499
+template 
+DL_PrivateKey_GFP::~DL_PrivateKey_GFP() {}
+
+/// \brief Discrete Log (DL) signing/verification keys in GF(p) groups
+struct DL_SignatureKeys_GFP
+{
+    typedef DL_GroupParameters_GFP GroupParameters;
+    typedef DL_PublicKey_GFP PublicKey;
+    typedef DL_PrivateKey_GFP PrivateKey;
+};
+
+/// \brief Discrete Log (DL) encryption/decryption keys in GF(p) groups
+struct DL_CryptoKeys_GFP
+{
+    typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
+    typedef DL_PublicKey_GFP PublicKey;
+    typedef DL_PrivateKey_GFP PrivateKey;
+};
+
+/// ElGamal encryption keys for safe interop
+/// \sa On the
+///  (in)security of ElGamal in OpenPGP,
+///  Issue 1059,
+///  CVE-2021-40530
+/// \since Crypto++ 8.6
+struct DL_CryptoKeys_ElGamal
+{
+    typedef DL_GroupParameters_ElGamal GroupParameters;
+    typedef DL_PublicKey_GFP PublicKey;
+    typedef DL_PrivateKey_GFP PrivateKey;
+};
+
+/// \brief DSA signature scheme
+/// \tparam H HashTransformation derived class
+/// \sa DSA-1363
+/// \since Crypto++ 1.0 for DSA, Crypto++ 5.6.2 for DSA2
+template 
+struct GDSA : public DL_SS<
+    DL_SignatureKeys_GFP,
+    DL_Algorithm_GDSA,
+    DL_SignatureMessageEncodingMethod_DSA,
+    H>
+{
+};
+
+/// \brief NR signature scheme
+/// \tparam H HashTransformation derived class
+/// \sa NR
+template 
+struct NR : public DL_SS<
+    DL_SignatureKeys_GFP,
+    DL_Algorithm_NR,
+    DL_SignatureMessageEncodingMethod_NR,
+    H>
+{
+};
+
+/// \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() {}
+
+    /// \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:
+    ///  
    + ///
  • 0 - using this object won't cause a crash or exception + ///
  • 1 - this object will probably function, and encrypt, sign, other operations correctly + ///
  • 2 - ensure this object will function correctly, and perform reasonable security checks + ///
  • 3 - perform reasonable security checks, and do checks that may take a long time + ///
+ /// \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; + + /// \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 DSA::MIN_PRIME_LENGTH and + /// DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE. + /// \details An example of changing the modulus size using NameValuePairs is shown below. + ///
+    ///  AlgorithmParameters params = MakeParameters
+    ///    (Name::ModulusSize(), 2048);
+    ///
+    ///  DL_GroupParameters_DSA groupParams;
+    ///  groupParams.GenerateRandom(prng, params);
+    /// 
+ /// \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;} + + /// \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 DSA2; + +/// \brief DSA keys +/// \sa DL_GroupParameters_DSA +/// \since Crypto++ 1.0 +struct DL_Keys_DSA +{ + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA2 > PrivateKey; +}; + +/// \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. +/// \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: +///
+///  DSA::PrivateKey privateKey;
+///  privateKey.GenerateRandomWithKeySize(prng, 2048);
+/// 
+/// \details The subgroup order can be changed using the following code: +///
+///  AlgorithmParameters params = MakeParameters
+///    (Name::ModulusSize(), 2048)
+///    (Name::SubgroupOrderSize(), 256);
+///
+///  DSA::PrivateKey privateKey;
+///  privateKey.GenerateRandom(prng, params);
+/// 
+/// \sa DSA, as specified in FIPS 186-3, +/// Digital Signature Algorithm on the wiki, and +/// NameValuePairs on the wiki. +/// \since Crypto++ 1.0 for DSA, Crypto++ 5.6.2 for DSA2, Crypto++ 6.1 for 2048-bit modulus. +template +class DSA2 : public DL_SS< + DL_Keys_DSA, + DL_Algorithm_GDSA, + DL_SignatureMessageEncodingMethod_DSA, + H, + DSA2 > +{ +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();} +}; + +/// \brief DSA deterministic signature scheme +/// \tparam H HashTransformation derived class +/// \sa DSA-1363 +/// \since Crypto++ 1.0 for DSA, Crypto++ 5.6.2 for DSA2 +template +struct DSA_RFC6979 : public DL_SS< + DL_SignatureKeys_GFP, + DL_Algorithm_DSA_RFC6979, + DL_SignatureMessageEncodingMethod_DSA, + H, + DSA_RFC6979 > +{ + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("DSA-RFC6979/") + H::StaticAlgorithmName();} +}; + +/// DSA with SHA-1, typedef'd for backwards compatibility +typedef DSA2 DSA; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA2 >; + +/// \brief P1363 based XOR Encryption Method +/// \tparam MAC MessageAuthenticationCode derived class used for MAC computation +/// \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 NoCofactorMultiplication, DHAES_MODE=false and LABEL_OCTETS=true. +/// \details If you need this method for Crypto++ 4.2 compatibility, then use the ECIES template class with +/// NoCofactorMultiplication, DHAES_MODE=false and LABEL_OCTETS=true. +/// \details If you need this method for Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES template class with +/// NoCofactorMultiplication, DHAES_MODE=true and LABEL_OCTETS=false. +/// \details Bouncy Castle 1.54 and Botan 1.11 compatibility are the default template parameters. +/// \since Crypto++ 4.0 +template +class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm +{ +public: + virtual ~DL_EncryptionAlgorithm_Xor() {} + + bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} + size_t GetSymmetricKeyLength(size_t plaintextLength) const + {return plaintextLength + static_cast(MAC::DEFAULT_KEYLENGTH);} + size_t GetSymmetricCiphertextLength(size_t plaintextLength) const + {return plaintextLength + static_cast(MAC::DIGESTSIZE);} + size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const + {return SaturatingSubtract(ciphertextLength, static_cast(MAC::DIGESTSIZE));} + void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const + { + CRYPTOPP_UNUSED(rng); + const byte *cipherKey = NULLPTR, *macKey = NULLPTR; + if (DHAES_MODE) + { + macKey = key; + cipherKey = key + MAC::DEFAULT_KEYLENGTH; + } + else + { + cipherKey = key; + macKey = key + plaintextLength; + } + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + if (plaintextLength) // Coverity finding + xorbuf(ciphertext, plaintext, cipherKey, plaintextLength); + + MAC mac(macKey); + mac.Update(ciphertext, plaintextLength); + mac.Update(encodingParameters.begin(), encodingParameters.size()); + if (DHAES_MODE) + { + byte L[8]; + PutWord(false, BIG_ENDIAN_ORDER, L, (LABEL_OCTETS ? word64(encodingParameters.size()) : 8 * word64(encodingParameters.size()))); + mac.Update(L, 8); + } + mac.Final(ciphertext + plaintextLength); + } + DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const + { + size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength); + const byte *cipherKey, *macKey; + if (DHAES_MODE) + { + macKey = key; + cipherKey = key + MAC::DEFAULT_KEYLENGTH; + } + else + { + cipherKey = key; + macKey = key + plaintextLength; + } + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + MAC mac(macKey); + mac.Update(ciphertext, plaintextLength); + mac.Update(encodingParameters.begin(), encodingParameters.size()); + if (DHAES_MODE) + { + byte L[8]; + PutWord(false, BIG_ENDIAN_ORDER, L, (LABEL_OCTETS ? word64(encodingParameters.size()) : 8 * word64(encodingParameters.size()))); + mac.Update(L, 8); + } + if (!mac.Verify(ciphertext + plaintextLength)) + return DecodingResult(); + + if (plaintextLength) // Coverity finding + xorbuf(plaintext, ciphertext, cipherKey, plaintextLength); + + return DecodingResult(plaintextLength); + } +}; + +/// \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 T can be Integer, ECP or EC2N. +template +class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm +{ +public: + virtual ~DL_KeyDerivationAlgorithm_P1363() {} + + bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;} + void Derive(const DL_GroupParameters ¶ms, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs ¶meters) const + { + SecByteBlock agreedSecret; + if (DHAES_MODE) + { + agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false)); + params.EncodeElement(true, ephemeralPublicKey, agreedSecret); + params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true)); + } + else + { + agreedSecret.New(params.GetEncodedElementSize(false)); + params.EncodeElement(false, agreedElement, agreedSecret); + } + + ConstByteArrayParameter derivationParameters; + parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters); + KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size()); + } +}; + +/// \brief Discrete Log Integrated Encryption Scheme +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \tparam HASH HashTransformation derived class used for key drivation and MAC computation +/// \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 +/// IND-CCA2, 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 NoCofactorMultiplication, DHAES_MODE=false and LABEL_OCTETS=true. +/// \details If you desire an Integrated Encryption Scheme with Crypto++ 4.2 compatibility, then use the DLIES template class with +/// NoCofactorMultiplication, DHAES_MODE=false and LABEL_OCTETS=true. +/// \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 NoCofactorMultiplication, DHAES_MODE=true and LABEL_OCTETS=false. +/// \details The default template parameters ensure compatibility with Bouncy Castle 1.54 and Botan 1.11. The combination of +/// IncompatibleCofactorMultiplication and DHAES_MODE=true 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. +///
+///    AutoSeededRandomPool prng;
+///    DL_PrivateKey_GFP key;
+///    key.Initialize(prng, 2048);
+///
+///    DLIES::Decryptor decryptor(key);
+///    DLIES::Encryptor encryptor(decryptor);
+/// 
+/// \sa ECIES, Discrete Log Integrated Encryption Scheme (DLIES), +/// Martínez, Encinas, and Ávila's A Survey of the Elliptic +/// Curve Integrated Encryption Schemes +/// \since Crypto++ 4.0, Crypto++ 5.7 for Bouncy Castle and Botan compatibility +template +struct DLIES + : public DL_ES< + DL_CryptoKeys_GFP, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE, LABEL_OCTETS>, + DLIES<> > +{ + static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/gost.h b/third_party/cryptoppwin/include/cryptopp/gost.h new file mode 100644 index 00000000..87082a11 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/gost.h @@ -0,0 +1,66 @@ +// gost.h - originally written and placed in the public domain by Wei Dai + +/// \file gost.h +/// \brief Classes for the GIST block cipher + +#ifndef CRYPTOPP_GOST_H +#define CRYPTOPP_GOST_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief GOST block cipher information +/// \since Crypto++ 2.1 +struct GOST_Info : public FixedBlockSize<8>, public FixedKeyLength<32> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "GOST";} +}; + +/// \brief GOST block cipher +/// \sa GOST +/// \since Crypto++ 2.1 +class GOST : public GOST_Info, public BlockCipherDocumentation +{ + /// \brief GOST block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + static void PrecalculateSTable(); + + static const byte sBox[8][16]; + static volatile bool sTableCalculated; + static word32 sTable[4][256]; + + FixedSizeSecBlock m_key; + }; + + /// \brief GOST block cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief GOST block cipher decryption operation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef GOST::Encryption GOSTEncryption; +typedef GOST::Decryption GOSTDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/gzip.h b/third_party/cryptoppwin/include/cryptopp/gzip.h new file mode 100644 index 00000000..437a5209 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/gzip.h @@ -0,0 +1,144 @@ +// gzip.h - originally written and placed in the public domain by Wei Dai + +/// \file gzip.h +/// \brief GZIP compression and decompression (RFC 1952) + +#ifndef CRYPTOPP_GZIP_H +#define CRYPTOPP_GZIP_H + +#include "cryptlib.h" +#include "zdeflate.h" +#include "zinflate.h" +#include "crc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief GZIP Compression (RFC 1952) +class Gzip : public Deflator +{ +public: + /// \brief Construct a Gzip compressor + /// \param attachment an attached transformation + /// \param deflateLevel the deflate level + /// \param log2WindowSize the window size + /// \param detectUncompressible flag to detect if data is compressible + /// \details detectUncompressible makes it faster to process uncompressible files, but + /// if a file has both compressible and uncompressible parts, it may fail to compress + /// some of the compressible parts. + Gzip(BufferedTransformation *attachment=NULLPTR, unsigned int deflateLevel=DEFAULT_DEFLATE_LEVEL, unsigned int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true) + : Deflator(attachment, deflateLevel, log2WindowSize, detectUncompressible), m_totalLen(0), m_filetime(0) { } + + /// \brief Construct a Gzip compressor + /// \param parameters a set of NameValuePairs to initialize this object + /// \param attachment an attached transformation + /// \details Possible parameter names: Log2WindowSize, DeflateLevel, DetectUncompressible + Gzip(const NameValuePairs ¶meters, BufferedTransformation *attachment=NULLPTR) + : Deflator(parameters, attachment), m_totalLen(0), m_filetime(0) + { + IsolatedInitialize(parameters); + } + + /// \param filetime the filetime to set in the header. The application is responsible for setting it. + void SetFiletime(word32 filetime) { m_filetime = filetime; } + + /// \param filename the original filename to set in the header. The application is responsible for setting it. + /// RFC 1952 requires a ISO/IEC 8859-1 encoding. + /// \param throwOnEncodingError if throwOnEncodingError is true, then the filename is checked to ensure it is + /// ISO/IEC 8859-1 encoded. If the filename does not adhere to ISO/IEC 8859-1, then a InvalidDataFormat + /// is thrown. If throwOnEncodingError is false then the filename is not checked. + void SetFilename(const std::string& filename, bool throwOnEncodingError = false); + + /// \param comment the comment to set in the header. The application is responsible for setting it. + /// RFC 1952 requires a ISO/IEC 8859-1 encoding. + /// \param throwOnEncodingError if throwOnEncodingError is true, then the comment is checked to ensure it is + /// ISO/IEC 8859-1 encoded. If the comment does not adhere to ISO/IEC 8859-1, then a InvalidDataFormat + /// is thrown. If throwOnEncodingError is false then the comment is not checked. + void SetComment(const std::string& comment, bool throwOnEncodingError = false); + + void IsolatedInitialize(const NameValuePairs ¶meters); + +protected: + enum {MAGIC1=0x1f, MAGIC2=0x8b, // flags for the header + DEFLATED=8, FAST=4, SLOW=2}; + + enum FLAG_MASKS { + FILENAME=8, COMMENTS=16}; + + void WritePrestreamHeader(); + void ProcessUncompressedData(const byte *string, size_t length); + void WritePoststreamTail(); + + word32 m_totalLen; + CRC32 m_crc; + + word32 m_filetime; + std::string m_filename; + std::string m_comment; +}; + +/// \brief GZIP Decompression (RFC 1952) +class Gunzip : public Inflator +{ +public: + typedef Inflator::Err Err; + + /// \brief Exception thrown when a header decoding error occurs + class HeaderErr : public Err {public: HeaderErr() : Err(INVALID_DATA_FORMAT, "Gunzip: header decoding error") {}}; + /// \brief Exception thrown when the tail is too short + class TailErr : public Err {public: TailErr() : Err(INVALID_DATA_FORMAT, "Gunzip: tail too short") {}}; + /// \brief Exception thrown when a CRC error occurs + class CrcErr : public Err {public: CrcErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: CRC check error") {}}; + /// \brief Exception thrown when a length error occurs + class LengthErr : public Err {public: LengthErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: length check error") {}}; + + /// \brief Construct a Gunzip decompressor + /// \param attachment an attached transformation + /// \param repeat decompress multiple compressed streams in series + /// \param autoSignalPropagation 0 to turn off MessageEnd signal + Gunzip(BufferedTransformation *attachment = NULLPTR, bool repeat = false, int autoSignalPropagation = -1); + + /// \return the filetime of the stream as set in the header. The application is responsible for setting it on the decompressed file. + word32 GetFiletime() const { return m_filetime; } + + /// \return the filename of the stream as set in the header. The application is responsible for setting it on the decompressed file. + /// \param throwOnEncodingError if throwOnEncodingError is true, then the filename is checked to ensure it is + /// ISO/IEC 8859-1 encoded. If the filename does not adhere to ISO/IEC 8859-1, then a InvalidDataFormat is thrown. + /// If throwOnEncodingError is false then the filename is not checked. + const std::string& GetFilename(bool throwOnEncodingError = false) const; + + /// \return the comment of the stream as set in the header. + /// \param throwOnEncodingError if throwOnEncodingError is true, then the comment is checked to ensure it is + /// ISO/IEC 8859-1 encoded. If the comment does not adhere to ISO/IEC 8859-1, then a InvalidDataFormat is thrown. + /// If throwOnEncodingError is false then the comment is not checked. + const std::string& GetComment(bool throwOnEncodingError = false) const; + +protected: + enum { + /// \brief First header magic value + MAGIC1=0x1f, + /// \brief Second header magic value + MAGIC2=0x8b, + /// \brief Deflated flag + DEFLATED=8 + }; + + enum FLAG_MASKS { + CONTINUED=2, EXTRA_FIELDS=4, FILENAME=8, COMMENTS=16, ENCRYPTED=32}; + + unsigned int MaxPrestreamHeaderSize() const {return 1024;} + void ProcessPrestreamHeader(); + void ProcessDecompressedData(const byte *string, size_t length); + unsigned int MaxPoststreamTailSize() const {return 8;} + void ProcessPoststreamTail(); + + word32 m_length; + CRC32 m_crc; + + word32 m_filetime; + std::string m_filename; + std::string m_comment; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/hashfwd.h b/third_party/cryptoppwin/include/cryptopp/hashfwd.h new file mode 100644 index 00000000..5e1309da --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/hashfwd.h @@ -0,0 +1,38 @@ +// hashfwd.h - written and placed in the public domain by Jeffrey Walton + +/// \file hashfwd.h +/// \brief Forward declarations for hash functions used in signature encoding methods + +#ifndef CRYPTOPP_HASHFWD_H +#define CRYPTOPP_HASHFWD_H + +#include "config.h" + +NAMESPACE_BEGIN(CryptoPP) + +class SHA1; +class SHA224; +class SHA256; +class SHA384; +class SHA512; + +class SHA3_256; +class SHA3_384; +class SHA3_512; + +class SHAKE128; +class SHAKE256; + +class Tiger; +class RIPEMD128; +class RIPEMD160; +class Whirlpool; + +namespace Weak1 { + class MD2; + class MD5; +} + +NAMESPACE_END + +#endif // CRYPTOPP_HASHFWD_H diff --git a/third_party/cryptoppwin/include/cryptopp/hc128.h b/third_party/cryptoppwin/include/cryptopp/hc128.h new file mode 100644 index 00000000..a35352c9 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 The +/// eSTREAM Project | HC-128 and +/// Crypto++ Wiki | HC-128. +/// \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, public HC128Info +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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 m_X; + FixedSizeSecBlock m_Y; + FixedSizeSecBlock m_key; + FixedSizeSecBlock 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 The +/// eSTREAM Project | HC-128 and +/// Crypto++ Wiki | HC-128. +/// \since Crypto++ 8.0 +struct HC128 : public HC128Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, HC128Info> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_HC128_H diff --git a/third_party/cryptoppwin/include/cryptopp/hc256.h b/third_party/cryptoppwin/include/cryptopp/hc256.h new file mode 100644 index 00000000..169d0b95 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 The +/// eSTREAM Project | HC-256 and +/// Crypto++ Wiki | HC-128. +/// \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, public HC256Info +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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 m_key; + FixedSizeSecBlock 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 The +/// eSTREAM Project | HC-256 and +/// Crypto++ Wiki | HC-128. +/// \since Crypto++ 8.0 +struct HC256 : public HC256Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, HC256Info> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_HC256_H diff --git a/third_party/cryptoppwin/include/cryptopp/hex.h b/third_party/cryptoppwin/include/cryptopp/hex.h new file mode 100644 index 00000000..bcf2bd03 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/hex.h @@ -0,0 +1,50 @@ +// hex.h - originally written and placed in the public domain by Wei Dai + +/// \file hex.h +/// \brief Classes for HexEncoder and HexDecoder + +#ifndef CRYPTOPP_HEX_H +#define CRYPTOPP_HEX_H + +#include "cryptlib.h" +#include "basecode.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Converts given data to base 16 +class CRYPTOPP_DLL HexEncoder : public SimpleProxyFilter +{ +public: + /// \brief Construct a HexEncoder + /// \param attachment a BufferedTrasformation to attach to this object + /// \param uppercase a flag indicating uppercase output + /// \param groupSize the size of the output grouping + /// \param separator the separator to use between groups + /// \param terminator the terminator append after processing + HexEncoder(BufferedTransformation *attachment = NULLPTR, bool uppercase = true, int groupSize = 0, const std::string &separator = ":", const std::string &terminator = "") + : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) + { + IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), groupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator))); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); +}; + +/// \brief Decode base 16 data back to bytes +class CRYPTOPP_DLL HexDecoder : public BaseN_Decoder +{ +public: + /// \brief Construct a HexDecoder + /// \param attachment a BufferedTrasformation to attach to this object + HexDecoder(BufferedTransformation *attachment = NULLPTR) + : BaseN_Decoder(GetDefaultDecodingLookupArray(), 4, attachment) {} + + void IsolatedInitialize(const NameValuePairs ¶meters); + +private: + static const int * CRYPTOPP_API GetDefaultDecodingLookupArray(); +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/hight.h b/third_party/cryptoppwin/include/cryptopp/hight.h new file mode 100644 index 00000000..c1ecd79a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 HIGHT, +/// Korea Internet & Security +/// Agency 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 + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + + FixedSizeSecBlock m_rkey; + mutable FixedSizeSecBlock 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; + typedef BlockCipherFinal Decryption; +}; + +typedef HIGHT::Encryption HIGHTEncryption; +typedef HIGHT::Decryption HIGHTDecryption; + +NAMESPACE_END + +#endif // CRYPTOPP_HIGHT_H diff --git a/third_party/cryptoppwin/include/cryptopp/hkdf.h b/third_party/cryptoppwin/include/cryptopp/hkdf.h new file mode 100644 index 00000000..490f212e --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/hkdf.h @@ -0,0 +1,179 @@ +// hkdf.h - written and placed in public domain by Jeffrey Walton. + +/// \file hkdf.h +/// \brief Classes for HKDF from RFC 5869 +/// \since Crypto++ 5.6.3 + +#ifndef CRYPTOPP_HKDF_H +#define CRYPTOPP_HKDF_H + +#include "cryptlib.h" +#include "secblock.h" +#include "algparam.h" +#include "hmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Extract-and-Expand Key Derivation Function (HKDF) +/// \tparam T HashTransformation class +/// \sa Cryptographic Extraction and Key +/// Derivation: The HKDF Scheme and +/// HMAC-based Extract-and-Expand Key +/// Derivation Function (HKDF) +/// \since Crypto++ 5.6.3 +template +class HKDF : public KeyDerivationFunction +{ +public: + virtual ~HKDF() {} + + static std::string StaticAlgorithmName () { + const std::string name(std::string("HKDF(") + + std::string(T::StaticAlgorithmName()) + std::string(")")); + return name; + } + + // KeyDerivationFunction interface + std::string AlgorithmName() const { + return StaticAlgorithmName(); + } + + // KeyDerivationFunction interface + size_t MaxDerivedKeyLength() const { + return static_cast(T::DIGESTSIZE) * 255; + } + + // KeyDerivationFunction interface + size_t GetValidDerivedLength(size_t keylength) const; + + // KeyDerivationFunction interface + size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const NameValuePairs& params) const; + + /// \brief Derive a key from a seed + /// \param derived the derived output buffer + /// \param derivedLen the size of the derived buffer, in bytes + /// \param secret the seed input buffer + /// \param secretLen the size of the secret buffer, in bytes + /// \param salt the salt input buffer + /// \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 + /// \return the number of iterations performed + /// \throw InvalidDerivedKeyLength if derivedLen 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. + /// \details salt and info can be nullptr with 0 length. + /// HKDF is unusual in that a non-NULL salt with length 0 is different than a + /// NULL salt. A NULL salt causes HKDF to use a string of 0's + /// of length T::DIGESTSIZE for the salt. + /// \details HKDF always returns 1 because it only performs 1 iteration. Other + /// derivation functions, like PBKDF's, will return more interesting values. + size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const; + +protected: + // KeyDerivationFunction interface + const Algorithm & GetAlgorithm() const { + return *this; + } + + // If salt is absent (NULL), then use the NULL vector. Missing is different than + // EMPTY (Non-NULL, 0 length). The length of s_NullVector used depends on the Hash + // function. SHA-256 will use 32 bytes of s_NullVector. + typedef byte NullVectorType[T::DIGESTSIZE]; + static const NullVectorType& GetNullVector() { + static const NullVectorType s_NullVector = {0}; + return s_NullVector; + } +}; + +template +size_t HKDF::GetValidDerivedLength(size_t keylength) const +{ + if (keylength > MaxDerivedKeyLength()) + return MaxDerivedKeyLength(); + return keylength; +} + +template +size_t HKDF::DeriveKey(byte *derived, size_t derivedLen, + const byte *secret, size_t secretLen, const NameValuePairs& params) const +{ + CRYPTOPP_ASSERT(secret && secretLen); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + + ConstByteArrayParameter p; + SecByteBlock salt, info; + + if (params.GetValue("Salt", p)) + salt.Assign(p.begin(), p.size()); + else + salt.Assign(GetNullVector(), T::DIGESTSIZE); + + if (params.GetValue("Info", p)) + info.Assign(p.begin(), p.size()); + else + info.Assign(GetNullVector(), 0); + + return DeriveKey(derived, derivedLen, secret, secretLen, salt.begin(), salt.size(), info.begin(), info.size()); +} + +template +size_t HKDF::DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const +{ + CRYPTOPP_ASSERT(secret && secretLen); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + + ThrowIfInvalidDerivedKeyLength(derivedLen); + + // HKDF business logic. NULL is different than empty. + if (salt == NULLPTR) + { + salt = GetNullVector(); + saltLen = T::DIGESTSIZE; + } + + // key is PRK from the RFC, salt is IKM from the RFC + HMAC hmac; + SecByteBlock key(T::DIGESTSIZE), buffer(T::DIGESTSIZE); + + // Extract + hmac.SetKey(salt, saltLen); + hmac.CalculateDigest(key, secret, secretLen); + + // Key + hmac.SetKey(key.begin(), key.size()); + byte block = 0; + + // Expand + while (derivedLen > 0) + { + if (block++) {hmac.Update(buffer, buffer.size());} + if (infoLen) {hmac.Update(info, infoLen);} + hmac.CalculateDigest(buffer, &block, 1); + +#if CRYPTOPP_MSC_VERSION + const size_t digestSize = static_cast(T::DIGESTSIZE); + const size_t segmentLen = STDMIN(derivedLen, digestSize); + memcpy_s(derived, segmentLen, buffer, segmentLen); +#else + const size_t digestSize = static_cast(T::DIGESTSIZE); + const size_t segmentLen = STDMIN(derivedLen, digestSize); + std::memcpy(derived, buffer, segmentLen); +#endif + + derived += segmentLen; + derivedLen -= segmentLen; + } + + return 1; +} + +NAMESPACE_END + +#endif // CRYPTOPP_HKDF_H diff --git a/third_party/cryptoppwin/include/cryptopp/hmac.h b/third_party/cryptoppwin/include/cryptopp/hmac.h new file mode 100644 index 00000000..79ba1aad --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/hmac.h @@ -0,0 +1,80 @@ +// hmac.h - originally written and placed in the public domain by Wei Dai + +/// \file hmac.h +/// \brief Classes for HMAC message authentication codes + +#ifndef CRYPTOPP_HMAC_H +#define CRYPTOPP_HMAC_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief HMAC information +/// \details HMAC_Base derives from VariableKeyLength and MessageAuthenticationCode +/// \since Crypto++ 2.1 +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 ¶ms); + + void Restart(); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int OptimalBlockSize() const {return const_cast(this)->AccessHash().OptimalBlockSize();} + unsigned int DigestSize() const {return const_cast(this)->AccessHash().DigestSize();} + +protected: + virtual HashTransformation & AccessHash() =0; + byte * AccessIpad() {return m_buf;} + byte * AccessOpad() {return m_buf + AccessHash().BlockSize();} + byte * AccessInnerHash() {return m_buf + 2*AccessHash().BlockSize();} + +private: + void KeyInnerHash(); + + SecByteBlock m_buf; + bool m_innerHashKeyed; +}; + +/// \brief HMAC +/// \tparam T HashTransformation derived class +/// \details HMAC derives from MessageAuthenticationCodeImpl. It calculates the HMAC using +/// HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)). +/// \sa HMAC +/// \since Crypto++ 2.1 +template +class HMAC : public MessageAuthenticationCodeImpl > +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE); + CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE); + + virtual ~HMAC() {} + + /// \brief Construct a HMAC + HMAC() {} + /// \brief Construct a HMAC + /// \param key the HMAC key + /// \param length the size of the HMAC key + HMAC(const byte *key, size_t length=HMAC_Base::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} + + 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;} + + T m_hash; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/hmqv.h b/third_party/cryptoppwin/include/cryptopp/hmqv.h new file mode 100644 index 00000000..4736b055 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/hmqv.h @@ -0,0 +1,417 @@ +// hmqv.h - written and placed in the public domain by Uri Blumenthal +// Shamelessly based upon Wei Dai's MQV source files + +#ifndef CRYPTOPP_HMQV_H +#define CRYPTOPP_HMQV_H + +/// \file hmqv.h +/// \brief Classes for Hashed Menezes-Qu-Vanstone key agreement in GF(p) +/// \since Crypto++ 5.6.4 + +#include "gfpcrypt.h" +#include "algebra.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Hashed Menezes-Qu-Vanstone in GF(p) +/// \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance +/// Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided. +/// \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain +/// \since Crypto++ 5.6.4 +template +class HMQV_Domain: public AuthenticatedKeyAgreementDomain +{ +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef HMQV_Domain Domain; + + virtual ~HMQV_Domain() {} + + /// \brief Construct a HMQV domain + /// \param clientRole flag indicating initiator or recipient + /// \details clientRole = true indicates initiator, and + /// clientRole = false 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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + HMQV_Domain(const GroupParameters ¶ms, 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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + HMQV_Domain(BufferedTransformation &bt, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + HMQV_Domain(T1 v1, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + HMQV_Domain(T1 v1, T2 v2, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true) + : m_role(clientRole ? RoleClient : RoleServer) + {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 clientRole = true indicates initiator, and + /// clientRole = false indicates recipient or server. + template + 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);} + +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;} + + /// \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 GetEncodedElementSize(false), + /// 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 GetEncodedElementSize(true), + /// 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 + /// [1,MaxExponent()]. + /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength() + void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + } + + /// \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 COUNTOF(publicKey) == PublicStaticKeyLength() + void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + 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 COUNTOF(privateKey) == EphemeralPrivateKeyLength() + void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(rng, Integer::One(), params.GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + 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 COUNTOF(publicKey) == EphemeralPublicKeyLength() + void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + 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. + /// validateStaticOtherPublicKey determines how thoroughly other's + /// static public key is validated. If you have previously validated the + /// couterparty's static public key, then use + /// validateStaticOtherPublicKey=false to save time. + /// \pre COUNTOF(agreedValue) == AgreedValueLength() + /// \pre COUNTOF(staticPrivateKey) == StaticPrivateKeyLength() + /// \pre COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength() + /// \pre COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength() + /// \pre COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength() + bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const + { + 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 + // (long term) public key. AA or BB will then point into tt. + SecByteBlock tt(StaticPublicKeyLength()); + + try + { + this->GetMaterial().DoQuickSanityCheck(); + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + + if(m_role == RoleServer) + { + Integer b(staticPrivateKey, StaticPrivateKeyLength()); + Element B = params.ExponentiateBase(b); + params.EncodeElement(true, B, tt); + + XX = ephemeralOtherPublicKey; + xxs = EphemeralPublicKeyLength(); + YY = ephemeralPrivateKey + StaticPrivateKeyLength(); + yys = EphemeralPublicKeyLength(); + AA = staticOtherPublicKey; + aas = StaticPublicKeyLength(); + BB = tt.BytePtr(); + bbs = tt.SizeInBytes(); + } + else + { + Integer a(staticPrivateKey, StaticPrivateKeyLength()); + Element A = params.ExponentiateBase(a); + params.EncodeElement(true, A, tt); + + XX = ephemeralPrivateKey + StaticPrivateKeyLength(); + xxs = EphemeralPublicKeyLength(); + YY = ephemeralOtherPublicKey; + yys = EphemeralPublicKeyLength(); + AA = tt.BytePtr(); + aas = tt.SizeInBytes(); + BB = staticOtherPublicKey; + bbs = StaticPublicKeyLength(); + } + + 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); + SecByteBlock dd(len), ee(len); + + // Compute $d = \hat{H}(X, \hat{B})$ + Hash(NULLPTR, XX, xxs, BB, bbs, 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()); + Integer e(ee.BytePtr(), ee.SizeInBytes()); + + Element sigma; + if(m_role == RoleServer) + { + Integer y(ephemeralPrivateKey, StaticPrivateKeyLength()); + Integer b(staticPrivateKey, StaticPrivateKeyLength()); + Integer s_B = (y + e * b) % q; + + Element A = params.DecodeElement(AA, false); + Element X = params.DecodeElement(XX, false); + + Element t1 = params.ExponentiateElement(A, d); + Element t2 = m_groupParameters.MultiplyElements(X, t1); + + // $\sigma_B}=(X \cdot A^{d})^{s_B} + sigma = params.ExponentiateElement(t2, s_B); + } + else + { + Integer x(ephemeralPrivateKey, StaticPrivateKeyLength()); + Integer a(staticPrivateKey, StaticPrivateKeyLength()); + Integer s_A = (x + d * a) % q; + + Element B = params.DecodeElement(BB, false); + Element Y = params.DecodeElement(YY, false); + + Element t3 = params.ExponentiateElement(B, e); + Element t4 = m_groupParameters.MultiplyElements(Y, t3); + + // $\sigma_A}=(Y \cdot B^{e})^{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; + } + +protected: + // Hash invocation by client and server differ only in what keys + // each provides. + + inline void Hash(const Element* sigma, + const byte* e1, size_t e1len, // Ephemeral key and key length + const byte* s1, size_t s1len, // Static key and key length + byte* digest, size_t dlen) const + { + HASH hash; + size_t idx = 0, req = dlen; + size_t blk = STDMIN(dlen, (size_t)HASH::DIGESTSIZE); + + if(sigma) + { + if (e1len != 0 || s1len != 0) { + CRYPTOPP_ASSERT(0); + } + //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) { + CRYPTOPP_ASSERT(0); + } + hash.Update(e1, e1len); + hash.Update(s1, s1len); + } + + hash.TruncatedFinal(digest, blk); + req -= blk; + + // All this to catch tail bytes for large curves and small hashes + while(req != 0) + { + hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); + + idx += (size_t)HASH::DIGESTSIZE; + blk = STDMIN(req, (size_t)HASH::DIGESTSIZE); + hash.TruncatedFinal(&digest[idx], blk); + + req -= blk; + } + } + +private: + + // The paper uses Initiator and Recipient - make it classical. + enum KeyAgreementRole { RoleServer = 1, RoleClient }; + + DL_GroupParameters & AccessAbstractGroupParameters() + {return m_groupParameters;} + const DL_GroupParameters & GetAbstractGroupParameters() const + {return m_groupParameters;} + + GroupParameters m_groupParameters; + KeyAgreementRole m_role; +}; + +/// \brief Hashed Menezes-Qu-Vanstone in GF(p) +/// \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance +/// Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided. +/// \sa HMQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain +/// \since Crypto++ 5.6.4 +typedef HMQV_Domain HMQV; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/hrtimer.h b/third_party/cryptoppwin/include/cryptopp/hrtimer.h new file mode 100644 index 00000000..db6ad180 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/hrtimer.h @@ -0,0 +1,134 @@ +// 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 + +#include "config.h" + +#if !defined(HIGHRES_TIMER_AVAILABLE) || (defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE)) +#include +#endif + +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: + /// \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) {} + + /// \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 Unit = SECONDS and ElapsedTimeAsDouble() returns 3, + /// then the timer has run for 3 seconds. If + /// Unit = MILLISECONDS 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 + /// Unit = SECONDS and ElapsedTime() returns 3, then + /// the timer has run for 3 seconds. If Unit = MILLISECONDS + /// and ElapsedTime() returns 3000, then the timer has run for 3 + /// seconds. + /// \sa Unit, ElapsedTimeAsDouble + unsigned long ElapsedTime(); + +private: + double ConvertTo(TimerWord t, Unit unit); + + Unit m_timerUnit; // HPUX workaround: m_unit is a system macro on HPUX + bool m_stuckAtZero, m_started; + TimerWord m_start, m_last; +}; + +/// \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(); +}; + +/// \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(); +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ida.h b/third_party/cryptoppwin/include/cryptopp/ida.h new file mode 100644 index 00000000..534a9ba7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ida.h @@ -0,0 +1,182 @@ +// ida.h - originally written and placed in the public domain by Wei Dai + +/// \file ida.h +/// \brief Classes for Rabin's Information Dispersal and Shamir's Secret Sharing algorithms + +#ifndef CRYPTOPP_IDA_H +#define CRYPTOPP_IDA_H + +#include "cryptlib.h" +#include "mqueue.h" +#include "filters.h" +#include "channels.h" +#include "secblock.h" +#include "gf2_32.h" +#include "stdcpp.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Secret sharing and information dispersal base class +/// \since Crypto++ 1.0 +class RawIDA : public AutoSignaling > > +{ +public: + RawIDA(BufferedTransformation *attachment=NULLPTR) + : m_channelsReady(0), m_channelsFinished(0), m_threshold (0) + {Detach(attachment);} + + unsigned int GetThreshold() const {return m_threshold;} + void AddOutputChannel(word32 channelId); + void ChannelData(word32 channelId, const byte *inString, size_t length, bool messageEnd); + lword InputBuffered(word32 channelId) const; + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) + { + if (!blocking) + throw BlockingInputOnly("RawIDA"); + ChannelData(StringToWord(channel), begin, length, messageEnd != 0); + return 0; + } + +protected: + virtual void FlushOutputQueues(); + virtual void OutputMessageEnds(); + + unsigned int InsertInputChannel(word32 channelId); + unsigned int LookupInputChannel(word32 channelId) const; + void ComputeV(unsigned int); + void PrepareInterpolation(); + void ProcessInputQueues(); + + typedef std::map InputChannelMap; + InputChannelMap m_inputChannelMap; + InputChannelMap::iterator m_lastMapPosition; + std::vector m_inputQueues; + std::vector m_inputChannelIds, m_outputChannelIds, m_outputToInput; + std::vector m_outputChannelIdStrings; + std::vector m_outputQueues; + std::vector > m_v; + SecBlock 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 +/// \details SecretSharing is a variant of Shamir's secret sharing algorithm +/// \sa SecretRecovery, SecretRecovery, InformationDispersal, InformationRecovery +/// \since Crypto++ 1.0 +class SecretSharing : public CustomFlushPropagation +{ +public: + /// \brief Construct a SecretSharing + SecretSharing(RandomNumberGenerator &rng, int threshold, int nShares, BufferedTransformation *attachment=NULLPTR, bool addPadding=true) + : m_rng(rng), m_ida(new OutputProxy(*this, true)) + { + Detach(attachment); + IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("NumberOfShares", nShares)("AddPadding", addPadding)); + } + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) {return m_ida.Flush(hardFlush, propagation, blocking);} + +protected: + RandomNumberGenerator &m_rng; + RawIDA m_ida; + bool m_pad; +}; + +/// \brief Shamir's Secret Sharing Algorithm +/// \details SecretSharing is a variant of Shamir's secret sharing algorithm +/// \sa SecretRecovery, SecretRecovery, InformationDispersal, InformationRecovery +/// \since Crypto++ 1.0 +class SecretRecovery : public RawIDA +{ +public: + /// \brief Construct a SecretRecovery + SecretRecovery(int threshold, BufferedTransformation *attachment=NULLPTR, bool removePadding=true) + : RawIDA(attachment) + {IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("RemovePadding", removePadding));} + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + +protected: + void FlushOutputQueues(); + void OutputMessageEnds(); + + bool m_pad; +}; + +/// a variant of Rabin's Information Dispersal Algorithm + +/// \brief Rabin's Information Dispersal Algorithm +/// \details InformationDispersal is a variant of Rabin's information dispersal algorithm +/// \sa SecretRecovery, SecretRecovery, InformationDispersal, InformationRecovery +/// \since Crypto++ 1.0 +class InformationDispersal : public CustomFlushPropagation +{ +public: + /// \brief Construct a InformationDispersal + InformationDispersal(int threshold, int nShares, BufferedTransformation *attachment=NULLPTR, bool addPadding=true) + : m_ida(new OutputProxy(*this, true)), m_pad(false), m_nextChannel(0) + { + Detach(attachment); + IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("NumberOfShares", nShares)("AddPadding", addPadding)); + } + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) {return m_ida.Flush(hardFlush, propagation, blocking);} + +protected: + RawIDA m_ida; + bool m_pad; + unsigned int m_nextChannel; +}; + +/// \brief Rabin's Information Dispersal Algorithm +/// \details InformationDispersal is a variant of Rabin's information dispersal algorithm +/// \sa SecretRecovery, SecretRecovery, InformationDispersal, InformationRecovery +/// \since Crypto++ 1.0 +class InformationRecovery : public RawIDA +{ +public: + /// \brief Construct a InformationRecovery + InformationRecovery(int threshold, BufferedTransformation *attachment=NULLPTR, bool removePadding=true) + : RawIDA(attachment), m_pad(false) + {IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("RemovePadding", removePadding));} + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + +protected: + void FlushOutputQueues(); + void OutputMessageEnds(); + + bool m_pad; + ByteQueue m_queue; +}; + +class PaddingRemover : public Unflushable +{ +public: + PaddingRemover(BufferedTransformation *attachment=NULLPTR) + : m_possiblePadding(false), m_zeroCount(0) {Detach(attachment);} + + void IsolatedInitialize(const NameValuePairs ¶meters) + {CRYPTOPP_UNUSED(parameters); m_possiblePadding = false;} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + + // GetPossiblePadding() == false at the end of a message indicates incorrect padding + bool GetPossiblePadding() const {return m_possiblePadding;} + +private: + bool m_possiblePadding; + lword m_zeroCount; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/idea.h b/third_party/cryptoppwin/include/cryptopp/idea.h new file mode 100644 index 00000000..f4846b3a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/idea.h @@ -0,0 +1,66 @@ +// idea.h - originally written and placed in the public domain by Wei Dai + +/// \file idea.h +/// \brief Classes for the IDEA block cipher + +#ifndef CRYPTOPP_IDEA_H +#define CRYPTOPP_IDEA_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief IDEA block cipher information +/// \since Crypto++ 1.0 +struct IDEA_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public FixedRounds<8> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "IDEA";} +}; + +/// \brief IDEA block cipher +/// \sa IDEA +/// \since Crypto++ 1.0 +class IDEA : public IDEA_Info, public BlockCipherDocumentation +{ +public: // made public for internal purposes +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + typedef word Word; +#else + typedef hword Word; +#endif + +private: + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + unsigned int OptimalDataAlignment() const {return 2;} + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + private: + void EnKey(const byte *); + void DeKey(); + FixedSizeSecBlock m_key; + + #ifdef IDEA_LARGECACHE + static inline void LookupMUL(word &a, word b); + void LookupKeyLogs(); + static void BuildLogTables(); + static volatile bool tablesBuilt; + static word16 log[0x10000], antilog[0x10000]; + #endif + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef IDEA::Encryption IDEAEncryption; +typedef IDEA::Decryption IDEADecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/integer.h b/third_party/cryptoppwin/include/cryptopp/integer.h new file mode 100644 index 00000000..05d7d6ae --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/integer.h @@ -0,0 +1,840 @@ +// integer.h - originally written and placed in the public domain by Wei Dai + +/// \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))(256**sizeof(int)). +/// \details Internally, the library uses a sign magnitude representation, and the class +/// has two data members. The first is a IntegerSecBlock (a SecBlock) 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 integer.cpp. +/// \since Crypto++ 1.0 + +#ifndef CRYPTOPP_INTEGER_H +#define CRYPTOPP_INTEGER_H + +#include "cryptlib.h" +#include "secblock.h" +#include "stdcpp.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// \struct InitializeInteger +/// \brief Performs static initialization of the Integer class +struct InitializeInteger +{ + InitializeInteger(); +}; + +// Always align, http://github.com/weidai11/cryptopp/issues/256 +typedef SecBlock > 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))(256**sizeof(int)). +/// \details Internally, the library uses a sign magnitude representation, and the class +/// has two data members. The first is a IntegerSecBlock (a SecBlock) 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 integer.cpp. +/// \since Crypto++ 1.0 +/// \nosubgrouping +class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object +{ +public: + /// \name ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + /// \brief Exception thrown when division by 0 is encountered + class DivideByZero : public Exception + { + public: + DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {} + }; + + /// \brief Exception thrown when a random number cannot be found that + /// satisfies the condition + class RandomNumberNotFound : public Exception + { + public: + RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {} + }; + + /// \enum Sign + /// \brief Used internally to represent the integer + /// \details Sign is used internally to represent the integer. It is also used in a few API functions. + /// \sa SetPositive(), SetNegative(), Signedness + enum Sign { + /// \brief the value is positive or 0 + POSITIVE=0, + /// \brief the value is negative + NEGATIVE=1}; + + /// \enum Signedness + /// \brief Used when importing and exporting integers + /// \details Signedness is usually used in API functions. + /// \sa Sign + enum Signedness { + /// \brief an unsigned value + UNSIGNED, + /// \brief a signed value + SIGNED}; + + /// \enum RandomNumberType + /// \brief Properties of a random integer + enum RandomNumberType { + /// \brief a number with no special properties + ANY, + /// \brief a number which is probabilistically prime + PRIME}; + //@} + + /// \name CREATORS + //@{ + /// \brief Creates the zero integer + Integer(); + + /// copy constructor + Integer(const Integer& t); + + /// \brief Convert from signed long + Integer(signed long value); + + /// \brief Convert from lword + /// \param sign enumeration indicating Sign + /// \param value the long word + Integer(Sign sign, lword value); + + /// \brief Convert from two words + /// \param sign enumeration indicating Sign + /// \param highWord the high word + /// \param lowWord the low word + Integer(Sign sign, word highWord, word lowWord); + + /// \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 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. + 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 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. + explicit Integer(const wchar_t *str, ByteOrder order = BIG_ENDIAN_ORDER); + + /// \brief Convert from a big-endian byte array + /// \param encodedInteger big-endian byte array + /// \param byteCount length of the byte array + /// \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. + Integer(const byte *encodedInteger, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER); + + /// \brief Convert from a big-endian array + /// \param bt BufferedTransformation object with big-endian byte array + /// \param byteCount length of the byte array + /// \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. + Integer(BufferedTransformation &bt, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER); + + /// \brief Convert from a BER encoded byte array + /// \param bt BufferedTransformation object with BER encoded byte array + explicit Integer(BufferedTransformation &bt); + + /// \brief Create a random integer + /// \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 [0, 2bitCount]. + Integer(RandomNumberGenerator &rng, size_t bitCount); + + /// \brief 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 + /// \return an Integer representing 1 + /// \details One() avoids calling constructors for frequently used integers + static const Integer & CRYPTOPP_API One(); + /// \brief Integer representing 2 + /// \return an Integer representing 2 + /// \details Two() avoids calling constructors for frequently used integers + static const Integer & CRYPTOPP_API Two(); + + /// \brief Create a random integer of special form + /// \param rng RandomNumberGenerator used to generate material + /// \param min the minimum value + /// \param max the maximum value + /// \param rnType RandomNumberType to specify the type + /// \param equiv the equivalence class based on the parameter \p mod + /// \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 {x | min \<= x \<= max and \p x is of rnType and x \% mod == equiv}. + /// 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 max \> lastSmallPrime*lastSmallPrime. \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 + /// \return the Integer 2e + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + static Integer CRYPTOPP_API Power2(size_t e); + //@} + + /// \name ENCODE/DECODE + //@{ + /// \brief Minimum number of bytes to encode this integer + /// \param sign enumeration indicating Signedness + /// \note The MinEncodedSize() of 0 is 1. + size_t MinEncodedSize(Signedness sign=UNSIGNED) const; + + /// \brief Encode in big-endian format + /// \param output big-endian byte array + /// \param outputLen length of the byte array + /// \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. + void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const; + + /// \brief Encode in big-endian format + /// \param bt BufferedTransformation object + /// \param outputLen length of the encoding + /// \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. + 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 + void DEREncode(BufferedTransformation &bt) const; + + /// \brief Encode absolute value as big-endian octet string + /// \param bt BufferedTransformation object + /// \param length the number of mytes to decode + void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const; + + /// \brief Encode absolute value in OpenPGP format + /// \param output big-endian byte array + /// \param bufferSize length of the byte array + /// \return length of the output + /// \details OpenPGPEncode places result into the buffer and returns the + /// 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 + /// \return length of the output + /// \details OpenPGPEncode places result into a BufferedTransformation object and returns the + /// number of bytes used for the encoding + size_t OpenPGPEncode(BufferedTransformation &bt) const; + + /// \brief Decode from big-endian byte array + /// \param input big-endian byte array + /// \param inputLen length of the byte array + /// \param sign enumeration indicating Signedness + void Decode(const byte *input, size_t inputLen, Signedness sign=UNSIGNED); + + /// \brief Decode nonnegative value from big-endian byte array + /// \param bt BufferedTransformation object + /// \param inputLen length of the byte array + /// \param sign enumeration indicating Signedness + /// \note bt.MaxRetrievable() \>= inputLen. + void Decode(BufferedTransformation &bt, size_t inputLen, Signedness sign=UNSIGNED); + + /// \brief Decode from BER format + /// \param input big-endian byte array + /// \param inputLen length of the byte array + void BERDecode(const byte *input, size_t inputLen); + + /// \brief Decode from BER format + /// \param bt BufferedTransformation object + void BERDecode(BufferedTransformation &bt); + + /// \brief Decode nonnegative value from big-endian octet string + /// \param bt BufferedTransformation object + /// \param length length of the byte array + void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length); + + /// \brief Exception thrown when an error is encountered decoding an OpenPGP integer + class OpenPGPDecodeErr : public Exception + { + public: + OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {} + }; + + /// \brief Decode from OpenPGP format + /// \param input big-endian byte array + /// \param inputLen length of the byte array + void OpenPGPDecode(const byte *input, size_t inputLen); + /// \brief Decode from OpenPGP format + /// \param bt BufferedTransformation object + void OpenPGPDecode(BufferedTransformation &bt); + //@} + + /// \name ACCESSORS + //@{ + /// \brief Determines if the Integer is convertable to Long + /// \return true if *this can be represented as a signed long + /// \sa ConvertToLong() + bool IsConvertableToLong() const; + /// \brief Convert the Integer to Long + /// \return equivalent signed long if possible, otherwise undefined + /// \sa IsConvertableToLong() + signed long ConvertToLong() const; + + /// \brief Determines the number of bits required to represent the Integer + /// \return number of significant bits + /// \details BitCount is calculated as floor(log2(abs(*this))) + 1. + unsigned int BitCount() const; + /// \brief Determines the number of bytes required to represent the Integer + /// \return number of significant bytes + /// \details ByteCount is calculated as ceiling(BitCount()/8). + unsigned int ByteCount() const; + /// \brief Determines the number of words required to represent the Integer + /// \return number of significant words + /// \details WordCount is calculated as ceiling(ByteCount()/sizeof(word)). + unsigned int WordCount() const; + + /// \brief Provides the i-th bit of the Integer + /// \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 + /// \return the i-th byte + byte GetByte(size_t i) const; + /// \brief Provides the low order bits of the Integer + /// \return n lowest bits of *this >> i + lword GetBits(size_t i, size_t n) const; + + /// \brief Determines if the Integer is 0 + /// \return true if the Integer is 0, false otherwise + bool IsZero() const {return !*this;} + /// \brief Determines if the Integer is non-0 + /// \return true if the Integer is non-0, false otherwise + bool NotZero() const {return !IsZero();} + /// \brief Determines if the Integer is negative + /// \return true if the Integer is negative, false otherwise + bool IsNegative() const {return sign == NEGATIVE;} + /// \brief Determines if the Integer is non-negative + /// \return true if the Integer is non-negative, false otherwise + bool NotNegative() const {return !IsNegative();} + /// \brief Determines if the Integer is positive + /// \return true if the Integer is positive, false otherwise + bool IsPositive() const {return NotNegative() && NotZero();} + /// \brief Determines if the Integer is non-positive + /// \return true if the Integer is non-positive, false otherwise + bool NotPositive() const {return !IsPositive();} + /// \brief Determines if the Integer is even parity + /// \return true if the Integer is even, false otherwise + bool IsEven() const {return GetBit(0) == 0;} + /// \brief Determines if the Integer is odd parity + /// \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 *this + t + Integer& operator+=(const Integer& t); + /// \brief Subtraction Assignment + /// \param t the other Integer + /// \return the result of *this - t + Integer& operator-=(const Integer& t); + /// \brief Multiplication Assignment + /// \param t the other Integer + /// \return the result of *this * t + /// \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 *this / t + Integer& operator/=(const Integer& t) {return *this = DividedBy(t);} + /// \brief Remainder Assignment + /// \param t the other Integer + /// \return the result of *this % t + /// \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 *this / t + Integer& operator/=(word t) {return *this = DividedBy(t);} + /// \brief Remainder Assignment + /// \param t the other word + /// \return the result of *this % t + /// \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 + /// \return 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. + /// \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. + /// \since Crypto++ 6.0 + Integer& operator&=(const Integer& t); + /// \brief Bitwise OR Assignment + /// \param t the second Integer + /// \return 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. + /// \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. + /// \since Crypto++ 6.0 + Integer& operator|=(const Integer& t); + /// \brief Bitwise XOR Assignment + /// \param t the other Integer + /// \return 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. + /// \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. + /// \since Crypto++ 6.0 + Integer& operator^=(const Integer& t); + + /// \brief Set this Integer to random integer + /// \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 [0, 2bitCount]. + /// \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 + /// \param rng RandomNumberGenerator used to generate material + /// \param min the minimum value + /// \param max the maximum value + /// \details The random integer created is uniformly distributed over [min, max]. + void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max); + + /// \brief Set this Integer to random integer of special form + /// \param rng RandomNumberGenerator used to generate material + /// \param min the minimum value + /// \param max the maximum value + /// \param rnType RandomNumberType to specify the type + /// \param equiv the equivalence class based on the parameter \p mod + /// \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 {x | min \<= x \<= max and \p x is of rnType and x \% mod == equiv}. + /// 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 max \> lastSmallPrime*lastSmallPrime. \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 + /// \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. + /// \details The example below generates a prime number using NameValuePairs that Integer + /// class recognizes. The names are not provided in argnames.h. + ///
+		///    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");
+		/// 
+ bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs); + + /// \brief Generate a random number + /// \param rng RandomNumberGenerator used to generate material + /// \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. + /// \details The example below generates a prime number using NameValuePairs that Integer + /// class recognizes. The names are not provided in argnames.h. + ///
+		///    AutoSeededRandomPool prng;
+		///    AlgorithmParameters params = MakeParameters("BitLength", 2048)
+		///                                               ("RandomNumberType", Integer::PRIME);
+		///    Integer x;
+		///    try { x.GenerateRandom(prng, params); }
+		///    catch (RandomNumberNotFound&) { x = -1; }
+		/// 
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) + { + if (!GenerateRandomNoThrow(rng, params)) + throw RandomNumberNotFound(); + } + + /// \brief Set the n-th bit to value + /// \details 0-based numbering. + void SetBit(size_t n, bool value=1); + + /// \brief Set the n-th byte to value + /// \details 0-based numbering. + void SetByte(size_t n, byte value); + + /// \brief Reverse the Sign of the Integer + void Negate(); + + /// \brief Sets the Integer to positive + void SetPositive() {sign = POSITIVE;} + + /// \brief Sets the Integer to negative + void SetNegative() {if (!!(*this)) sign = NEGATIVE;} + + /// \brief Swaps this Integer with another Integer + void swap(Integer &a); + //@} + + /// \name UNARY OPERATORS + //@{ + /// \brief Negation + bool operator!() const; + /// \brief Addition + Integer operator+() const {return *this;} + /// \brief Subtraction + Integer operator-() const; + /// \brief Pre-increment + Integer& operator++(); + /// \brief Pre-decrement + Integer& operator--(); + /// \brief Post-increment + Integer operator++(int) {Integer temp = *this; ++*this; return temp;} + /// \brief Post-decrement + Integer operator--(int) {Integer temp = *this; --*this; return temp;} + //@} + + /// \name BINARY OPERATORS + //@{ + /// \brief Perform signed comparison + /// \param a the Integer to compare + /// \retval -1 if *this < a + /// \retval 0 if *this = a + /// \retval 1 if *this > a + int Compare(const Integer& a) const; + + /// \brief Addition + Integer Plus(const Integer &b) const; + /// \brief Subtraction + Integer Minus(const Integer &b) const; + /// \brief Multiplication + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + Integer Times(const Integer &b) const; + /// \brief Division + Integer DividedBy(const Integer &b) const; + /// \brief Remainder + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + Integer Modulo(const Integer &b) const; + /// \brief Division + Integer DividedBy(word b) const; + /// \brief Remainder + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + word Modulo(word b) const; + + /// \brief Bitwise AND + /// \param t the other Integer + /// \return the result of *this & t + /// \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. + /// \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. + /// \since Crypto++ 6.0 + Integer And(const Integer& t) const; + + /// \brief Bitwise OR + /// \param t the other Integer + /// \return the result of *this | t + /// \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. + /// \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. + /// \since Crypto++ 6.0 + Integer Or(const Integer& t) const; + + /// \brief Bitwise XOR + /// \param t the other Integer + /// \return the result of *this ^ t + /// \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. + /// \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. + /// \since Crypto++ 6.0 + Integer Xor(const Integer& t) const; + + /// \brief Right-shift + Integer operator>>(size_t n) const {return Integer(*this)>>=n;} + /// \brief Left-shift + Integer operator<<(size_t n) const {return Integer(*this)<<=n;} + //@} + + /// \name OTHER ARITHMETIC FUNCTIONS + //@{ + /// \brief Retrieve the absolute value of this integer + Integer AbsoluteValue() const; + /// \brief Add this integer to itself + Integer Doubled() const {return Plus(*this);} + /// \brief Multiply this integer by itself + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + Integer Squared() const {return Times(*this);} + /// \brief Extract square root + /// \details if negative return 0, else return floor of square root + Integer SquareRoot() const; + /// \brief Determine whether this integer is a perfect square + bool IsSquare() const; + + /// \brief Determine if 1 or -1 + /// \return true if this integer is 1 or -1, false otherwise + bool IsUnit() const; + /// \brief Calculate multiplicative inverse + /// \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 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 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. + 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 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. + static void CRYPTOPP_API DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n); + + /// \brief Calculate greatest common divisor + /// \param a reference to the first number + /// \param n reference to the secind number + /// \return the greatest common divisor a and n. + static Integer CRYPTOPP_API Gcd(const Integer &a, const Integer &n); + + /// \brief Calculate multiplicative inverse + /// \param n reference to the modulus + /// \return an Integer *this % n. + /// \details InverseMod returns the multiplicative inverse of the Integer *this + /// modulo the Integer n. If no Integer exists then Integer 0 is returned. + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + Integer InverseMod(const Integer &n) const; + + /// \brief Calculate multiplicative inverse + /// \param n the modulus + /// \return a word *this % n. + /// \details InverseMod returns the multiplicative inverse of the Integer *this + /// modulo the word n. If no Integer exists then word 0 is returned. + /// \sa a_times_b_mod_c() and a_exp_b_mod_c() + word InverseMod(word n) const; + //@} + + /// \name INPUT/OUTPUT + //@{ + /// \brief Extraction operator + /// \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 reference to a std::ostream + /// \param a a constant reference to an Integer + /// \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(). + /// \sa IntToString + friend CRYPTOPP_DLL std::ostream& CRYPTOPP_API operator<<(std::ostream& out, const Integer &a); + //@} + + /// \brief Modular multiplication + /// \param x reference to the first term + /// \param y reference to the second term + /// \param m reference to the modulus + /// \return an Integer (a * b) % m. + 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 reference to the base + /// \param e reference to the exponent + /// \param m reference to the modulus + /// \return an Integer (a ^ b) % m. + CRYPTOPP_DLL friend Integer CRYPTOPP_API a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m); + +protected: + + // http://github.com/weidai11/cryptopp/issues/602 + Integer InverseModNext(const Integer &n) const; + +private: + + Integer(word value, size_t length); + int PositiveCompare(const Integer &t) const; + + IntegerSecBlock reg; + Sign sign; + +#ifndef CRYPTOPP_DOXYGEN_PROCESSING + friend class ModularArithmetic; + friend class MontgomeryRepresentation; + friend class HalfMontgomeryRepresentation; + + friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b); + friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b); + friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b); + friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor); +#endif +}; + +/// \brief Comparison +inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;} +/// \brief Comparison +inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;} +/// \brief Comparison +inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;} +/// \brief Comparison +inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;} +/// \brief Comparison +inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;} +/// \brief Comparison +inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;} +/// \brief Addition +inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);} +/// \brief Subtraction +inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);} +/// \brief Multiplication +/// \sa a_times_b_mod_c() and a_exp_b_mod_c() +inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);} +/// \brief Division +inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);} +/// \brief Remainder +/// \sa a_times_b_mod_c() and a_exp_b_mod_c() +inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);} +/// \brief Division +inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);} +/// \brief Remainder +/// \sa a_times_b_mod_c() and a_exp_b_mod_c() +inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);} + +/// \brief Bitwise AND +/// \param a the first Integer +/// \param b the second Integer +/// \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. +/// \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. +/// \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 +/// \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. +/// \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. +/// \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 +/// \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. +/// \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. +/// \since Crypto++ 6.0 +inline CryptoPP::Integer operator^(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Xor(b);} + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/iterhash.h b/third_party/cryptoppwin/include/cryptopp/iterhash.h new file mode 100644 index 00000000..af916d9c --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/iterhash.h @@ -0,0 +1,218 @@ +// 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 + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" +#include "simple.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6011 6386 28193) +# endif +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Exception thrown when trying to hash more data than is allowed by a hash function +class CRYPTOPP_DLL HashInputTooLong : public InvalidDataFormat +{ +public: + explicit HashInputTooLong(const std::string &alg) + : InvalidDataFormat("IteratedHashBase: input data exceeds maximum allowed by hash function " + alg) {} +}; + +/// \brief Iterated hash base class +/// \tparam T Hash word type +/// \tparam BASE HashTransformation derived class +/// \details IteratedHashBase provides an interface for block-based iterated hashes +/// \sa HashTransformation, MessageAuthenticationCode +template +class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE +{ +public: + typedef T HashWordType; + + virtual ~IteratedHashBase() {} + + /// \brief Construct an IteratedHashBase + IteratedHashBase() : m_countLo(0), m_countHi(0) {} + + /// \brief Provides the input block size most efficient for this cipher. + /// \return The input block size that is most efficient for the cipher + /// \details The base class implementation returns MandatoryBlockSize(). + /// \note Optimal input length is + /// n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n \> 0. + unsigned int OptimalBlockSize() const {return this->BlockSize();} + + /// \brief Provides input and output data alignment for optimal performance. + /// \return the input data alignment that provides optimal performance + /// \details OptimalDataAlignment returns the natural alignment of the hash word. + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + /// \brief Updates a hash with additional input + /// \param input the additional input as a buffer + /// \param length the size of the buffer, in bytes + void Update(const byte *input, size_t length); + + /// \brief Requests space which can be written into by the caller + /// \param size the requested size of the buffer + /// \details The purpose of this method is to help avoid extra memory allocations. + /// \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made, + /// size is the requested size of the buffer. When the call returns, size is the size of + /// the array returned to the caller. + /// \details The base class implementation sets size to 0 and returns NULL. + /// \note Some objects, like ArraySink, cannot create a space because its fixed. + byte * CreateUpdateSpace(size_t &size); + + /// \brief Restart the hash + /// \details Discards the current state, and restart for a new message + void Restart(); + + /// \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() 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;} + + void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80); + virtual void Init() =0; + + 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());} + + virtual T* DataBuf() =0; + virtual T* StateBuf() =0; + +private: + T m_countLo, m_countHi; +}; + +/// \brief Iterated hash base class +/// \tparam T_HashWordType Hash word type +/// \tparam T_Endianness Endianness type of hash +/// \tparam T_BlockSize Block size of the hash +/// \tparam T_Base HashTransformation derived class +/// \details IteratedHash provides a default implementation for block-based iterated hashes +/// \sa HashTransformation, MessageAuthenticationCode +template +class CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase +{ +public: + typedef T_Endianness ByteOrderClass; + typedef T_HashWordType HashWordType; + + 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 + + virtual ~IteratedHash() {} + + /// \brief Provides the block size of the hash + /// \return the block size of the hash, in bytes + /// \details BlockSize() returns T_BlockSize. + unsigned int BlockSize() const {return T_BlockSize;} + + /// \brief Provides the byte order of the hash + /// \return the byte order of the hash as an enumeration + /// \details GetByteOrder() returns T_Endianness::ToEnum(). + /// \sa ByteOrder() + ByteOrder GetByteOrder() const {return T_Endianness::ToEnum();} + + /// \brief Adjusts the byte ordering of the hash + /// \param out the output buffer + /// \param in the input buffer + /// \param byteCount the size of the buffers, in bytes + /// \details CorrectEndianess() calls ConditionalByteReverse() using T_Endianness. + inline void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount) + { + CRYPTOPP_ASSERT(in != NULLPTR); + CRYPTOPP_ASSERT(out != NULLPTR); + CRYPTOPP_ASSERT(IsAligned(in)); + CRYPTOPP_ASSERT(IsAligned(out)); + + ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount); + } + +protected: + enum { Blocks = T_BlockSize/sizeof(T_HashWordType) }; + T_HashWordType* DataBuf() {return this->m_data;} + FixedSizeSecBlock m_data; +}; + +/// \brief Iterated hash with a static transformation function +/// \tparam T_HashWordType Hash word type +/// \tparam T_Endianness Endianness type of hash +/// \tparam T_BlockSize Block size of the hash +/// \tparam T_StateSize Internal state size of the hash +/// \tparam T_Transform HashTransformation derived class +/// \tparam T_DigestSize Digest size of the hash +/// \tparam T_StateAligned Flag indicating if state is 16-byte aligned +/// \sa HashTransformation, MessageAuthenticationCode +template +class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform + : public ClonableImpl, T_Transform> > +{ +public: + 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 DIGESTSIZE. + unsigned int DigestSize() const {return DIGESTSIZE;} + +protected: + // 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 m_state; +}; + +#if !defined(__GNUC__) && !defined(__clang__) + CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; + CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; + + CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; + CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; +#endif + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/kalyna.h b/third_party/cryptoppwin/include/cryptopp/kalyna.h new file mode 100644 index 00000000..0466ac14 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/kalyna.h @@ -0,0 +1,218 @@ +// kalyna.h - written and placed in the public domain by Jeffrey Walton +// Based on public domain code by Keru Kuro. + +/// \file kalyna.h +/// \brief Classes for the Kalyna block cipher +/// \details The Crypto++ implementation relied upon three sources. First was Oliynykov, Gorbenko, Kazymyrov, +/// Ruzhentsev, Kuznetsov, Gorbenko, Dyrda, Dolgov, Pushkaryov, Mordvinov and Kaidalov's "A New Encryption +/// Standard of Ukraine: The Kalyna Block Cipher" (http://eprint.iacr.org/2015/650.pdf). Second was Roman +/// Oliynykov and Oleksandr Kazymyrov's GitHub with the reference implementation +/// (http://github.com/Roman-Oliynykov/Kalyna-reference). The third resource was Keru Kuro's implementation +/// of Kalyna in CppCrypto (http://sourceforge.net/projects/cppcrypto/). Kuro has an outstanding +/// implementation that performed better than the reference implementation and our initial attempts. + +#ifndef CRYPTOPP_KALYNA_H +#define CRYPTOPP_KALYNA_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Kalyna-128 block cipher information +/// \since Crypto++ 6.0 +struct CRYPTOPP_NO_VTABLE Kalyna128_Info : public FixedBlockSize<16>, VariableKeyLength<16, 16, 32> +{ + static const char* StaticAlgorithmName() + { + // Format is Cipher-Blocksize(Keylength) + return "Kalyna-128"; + } +}; + +/// \brief Kalyna-256 block cipher information +/// \since Crypto++ 6.0 +struct CRYPTOPP_NO_VTABLE Kalyna256_Info : public FixedBlockSize<32>, VariableKeyLength<32, 32, 64> +{ + static const char* StaticAlgorithmName() + { + // Format is Cipher-Blocksize(Keylength) + return "Kalyna-256"; + } +}; + +/// \brief Kalyna-512 block cipher information +/// \since Crypto++ 6.0 +struct CRYPTOPP_NO_VTABLE Kalyna512_Info : public FixedBlockSize<64>, FixedKeyLength<64> +{ + static const char* StaticAlgorithmName() + { + // Format is Cipher-Blocksize(Keylength) + return "Kalyna-512"; + } +}; + +/// \brief Kalyna block cipher base class +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE Kalyna_Base +{ +public: + virtual ~Kalyna_Base() {} + +protected: + typedef SecBlock > AlignedSecBlock64; + mutable AlignedSecBlock64 m_wspace; // work space + AlignedSecBlock64 m_mkey; // master key + AlignedSecBlock64 m_rkeys; // round keys + unsigned int m_kl, m_nb, m_nk; // number 64-bit blocks and keys +}; + +/// \brief Kalyna 128-bit block cipher +/// \details Kalyna128 provides 128-bit block size. The valid key sizes are 128-bit and 256-bit. +/// \since Crypto++ 6.0 +class Kalyna128 : public Kalyna128_Info, public BlockCipherDocumentation +{ +public: + class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl + { + public: + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + /// \details If the object is unkeyed, then the generic name "Kalyna" is returned + /// to the caller. If the algorithm is keyed, then a two or three part name is + /// returned to the caller. The name follows DSTU 7624:2014, where block size is + /// provided first and then key length. The library uses a dash to identify block size + /// and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna + /// with a 128-bit block size and a 256-bit key length. If a mode is associated + /// with the object, then it follows as expected. For example, Kalyna-128(256)/ECB. + /// DSTU is a little more complex with more parameters, dashes, underscores, but the + /// library does not use the delimiters or full convention. + std::string AlgorithmName() const { + return std::string("Kalyna-128") + "(" + IntToString(m_kl*8) + ")"; + } + + /// \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 GetAlignmentOf(); + } + + protected: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + void SetKey_22(const word64 key[2]); + void SetKey_24(const word64 key[4]); + 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; + typedef BlockCipherFinal Decryption; +}; + +/// \brief Kalyna 256-bit block cipher +/// \details Kalyna256 provides 256-bit block size. The valid key sizes are 256-bit and 512-bit. +/// \since Crypto++ 6.0 +class Kalyna256 : public Kalyna256_Info, public BlockCipherDocumentation +{ +public: + class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl + { + public: + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + /// \details If the object is unkeyed, then the generic name "Kalyna" is returned + /// to the caller. If the algorithm is keyed, then a two or three part name is + /// returned to the caller. The name follows DSTU 7624:2014, where block size is + /// provided first and then key length. The library uses a dash to identify block size + /// and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna + /// with a 128-bit block size and a 256-bit key length. If a mode is associated + /// with the object, then it follows as expected. For example, Kalyna-128(256)/ECB. + /// DSTU is a little more complex with more parameters, dashes, underscores, but the + /// library does not use the delimiters or full convention. + std::string AlgorithmName() const { + return std::string("Kalyna-256") + "(" + IntToString(m_kl*8) + ")"; + } + + /// \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 GetAlignmentOf(); + } + + protected: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + void SetKey_44(const word64 key[4]); + void SetKey_48(const word64 key[8]); + 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; + typedef BlockCipherFinal Decryption; +}; + +/// \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 : public Kalyna512_Info, public BlockCipherDocumentation +{ +public: + class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl + { + public: + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + /// \details If the object is unkeyed, then the generic name "Kalyna" is returned + /// to the caller. If the algorithm is keyed, then a two or three part name is + /// returned to the caller. The name follows DSTU 7624:2014, where block size is + /// provided first and then key length. The library uses a dash to identify block size + /// and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna + /// with a 128-bit block size and a 256-bit key length. If a mode is associated + /// with the object, then it follows as expected. For example, Kalyna-128(256)/ECB. + /// DSTU is a little more complex with more parameters, dashes, underscores, but the + /// library does not use the delimiters or full convention. + std::string AlgorithmName() const { + return std::string("Kalyna-512") + "(" + IntToString(m_kl*8) + ")"; + } + + /// \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 GetAlignmentOf(); + } + + protected: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + void SetKey_88(const word64 key[8]); + void ProcessBlock_88(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Kalyna128::Encryption Kalyna128Encryption; +typedef Kalyna128::Decryption Kalyna128Decryption; + +typedef Kalyna256::Encryption Kalyna256Encryption; +typedef Kalyna256::Decryption Kalyna256Decryption; + +typedef Kalyna512::Encryption Kalyna512Encryption; +typedef Kalyna512::Decryption Kalyna512Decryption; + +NAMESPACE_END + +#endif // CRYPTOPP_KALYNA_H diff --git a/third_party/cryptoppwin/include/cryptopp/keccak.h b/third_party/cryptoppwin/include/cryptopp/keccak.h new file mode 100644 index 00000000..2d9e3603 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/keccak.h @@ -0,0 +1,118 @@ +// keccak.h - originally written and placed in the public domain by Wei Dai + +/// \file keccak.h +/// \brief Classes for Keccak message digests +/// \details The Crypto++ Keccak implementation uses F1600 with XOF d=0x01. +/// FIPS 202 conformance (XOF d=0x06) is available in SHA3 classes. +/// \details Keccak will likely change in the future to accommodate extensibility of the +/// round function and the XOF functions. +/// \sa Keccak +/// \since Crypto++ 5.6.4 + +#ifndef CRYPTOPP_KECCAK_H +#define CRYPTOPP_KECCAK_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Keccak message digest base class +/// \details The Crypto++ Keccak implementation uses F1600 with XOF d=0x01. +/// FIPS 202 conformance (XOF d=0x06) is available in SHA3 classes. +/// \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 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 value for r() (which will be 200-2*24 = 152). +///
  Keccack_192 : public Keccack
+///   {
+///     public:
+///       CRYPTOPP_CONSTANT(DIGESTSIZE = 24);
+///       Keccack_192() : Keccack(DIGESTSIZE) {}
+///   };
+///   
+/// +/// \sa SHA3, Keccak_224, Keccak_256, Keccak_384 and Keccak_512. +/// \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: + unsigned int DigestSize() const {return m_digestSize;} + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + void Update(const byte *input, size_t length); + void Restart(); + void TruncatedFinal(byte *hash, size_t size); + +protected: + inline unsigned int r() const {return BlockSize();} + + FixedSizeSecBlock m_state; + unsigned int m_digestSize, m_counter; +}; + +/// \brief Keccak message digest template +/// \tparam T_DigestSize the size of the digest, in bytes +/// \since Crypto++ 6.0 +template +class Keccak_Final : public Keccak +{ +public: + 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 r. + unsigned int BlockSize() const { return BLOCKSIZE; } + + std::string AlgorithmName() const { return StaticAlgorithmName(); } + +private: +#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 +DOCUMENTED_TYPEDEF(Keccak_Final<28>, Keccak_224); + +/// \brief Keccak-256 message digest +/// \since Crypto++ 5.6.4 +DOCUMENTED_TYPEDEF(Keccak_Final<32>, Keccak_256); + +/// \brief Keccak-384 message digest +/// \since Crypto++ 5.6.4 +DOCUMENTED_TYPEDEF(Keccak_Final<48>, Keccak_384); + +/// \brief Keccak-512 message digest +/// \since Crypto++ 5.6.4 +DOCUMENTED_TYPEDEF(Keccak_Final<64>, Keccak_512); + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/lea.h b/third_party/cryptoppwin/include/cryptopp/lea.h new file mode 100644 index 00000000..3ede3813 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 LEA, +/// +/// LEA: A 128-Bit Block Cipher for Fast Encryption on Common Processors +/// \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 + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + std::string AlgorithmProvider() const; + + SecBlock m_rkey; + mutable SecBlock 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; + typedef BlockCipherFinal Decryption; +}; + +typedef LEA::Encryption LEAEncryption; +typedef LEA::Decryption LEADecryption; + +NAMESPACE_END + +#endif // CRYPTOPP_LEA_H diff --git a/third_party/cryptoppwin/include/cryptopp/lsh.h b/third_party/cryptoppwin/include/cryptopp/lsh.h new file mode 100644 index 00000000..f89630a7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 LSH +/// 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(); } + + 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 m_state; + // word32 m_algType, m_remainingBitLength; + word32 m_digestSize; +}; + +/// \brief LSH-224 hash function +/// \sa LSH +/// 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 AES or AES/GCM. + /// 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 LSH +/// 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 AES or AES/GCM. + /// 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(); } + + 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 m_state; + // word32 m_algType, m_remainingBitLength; + word32 m_digestSize; +}; + +/// \brief LSH-384 hash function +/// \sa LSH +/// 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 AES or AES/GCM. + /// 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 LSH +/// 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 AES or AES/GCM. + /// 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 LSH +/// 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 AES or AES/GCM. + /// 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 diff --git a/third_party/cryptoppwin/include/cryptopp/lubyrack.h b/third_party/cryptoppwin/include/cryptopp/lubyrack.h new file mode 100644 index 00000000..e671303d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/lubyrack.h @@ -0,0 +1,137 @@ +// lubyrack.h - originally written and placed in the public domain by Wei Dai + +/// \file lubyrack.h +/// \brief Classes for the Luby-Rackoff block cipher + +#ifndef CRYPTOPP_LUBYRACK_H +#define CRYPTOPP_LUBYRACK_H + +#include "simple.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Luby-Rackoff block cipher information +template +struct LR_Info : public VariableKeyLength<16, 0, 2*(INT_MAX/2), 2>, public FixedBlockSize<2*T::DIGESTSIZE> +{ + static std::string StaticAlgorithmName() {return std::string("LR/")+T::StaticAlgorithmName();} +}; + +/// \brief Luby-Rackoff block cipher +template +class LR : public LR_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl > + { + public: + // VC60 workaround: have to define these functions within class definition + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) + { + this->AssertValidKeyLength(length); + + L = length/2; + buffer.New(2*S); + digest.New(S); + key.Assign(userKey, 2*L); + } + + protected: + CRYPTOPP_CONSTANT(S=T::DIGESTSIZE); + unsigned int L; // key length / 2 + SecByteBlock key; + + mutable T hm; + mutable SecByteBlock buffer, digest; + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + +#define KL this->key +#define KR this->key+this->L +#define BL this->buffer +#define BR this->buffer+this->S +#define IL inBlock +#define IR inBlock+this->S +#define OL outBlock +#define OR outBlock+this->S + + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const + { + this->hm.Update(KL, this->L); + this->hm.Update(IL, this->S); + this->hm.Final(BR); + xorbuf(BR, IR, this->S); + + this->hm.Update(KR, this->L); + this->hm.Update(BR, this->S); + this->hm.Final(BL); + xorbuf(BL, IL, this->S); + + this->hm.Update(KL, this->L); + this->hm.Update(BL, this->S); + this->hm.Final(this->digest); + xorbuf(BR, this->digest, this->S); + + this->hm.Update(KR, this->L); + this->hm.Update(OR, this->S); + this->hm.Final(this->digest); + xorbuf(BL, this->digest, this->S); + + if (xorBlock) + xorbuf(outBlock, xorBlock, this->buffer, 2*this->S); + else + memcpy_s(outBlock, 2*this->S, this->buffer, 2*this->S); + } + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const + { + this->hm.Update(KR, this->L); + this->hm.Update(IR, this->S); + this->hm.Final(BL); + xorbuf(BL, IL, this->S); + + this->hm.Update(KL, this->L); + this->hm.Update(BL, this->S); + this->hm.Final(BR); + xorbuf(BR, IR, this->S); + + this->hm.Update(KR, this->L); + this->hm.Update(BR, this->S); + this->hm.Final(this->digest); + xorbuf(BL, this->digest, this->S); + + this->hm.Update(KL, this->L); + this->hm.Update(OL, this->S); + this->hm.Final(this->digest); + xorbuf(BR, this->digest, this->S); + + if (xorBlock) + xorbuf(outBlock, xorBlock, this->buffer, 2*this->S); + else + std::memcpy(outBlock, this->buffer, 2*this->S); + } +#undef KL +#undef KR +#undef BL +#undef BR +#undef IL +#undef IR +#undef OL +#undef OR + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/luc.h b/third_party/cryptoppwin/include/cryptopp/luc.h new file mode 100644 index 00000000..7c0c1b7c --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/luc.h @@ -0,0 +1,338 @@ +// luc.h - originally written and placed in the public domain by Wei Dai + +/// \file luc.h +/// \brief Classes for the LUC cryptosystem +/// \details This class is here for historical and pedagogical interest. It has no practical advantages over other +/// trapdoor functions and probably shouldn't be used in production software. The discrete log based LUC schemes +/// defined later in this .h file may be of more practical interest. +/// \since Crypto++ 2.1 + +#ifndef CRYPTOPP_LUC_H +#define CRYPTOPP_LUC_H + +#include "cryptlib.h" +#include "gfpcrypt.h" +#include "integer.h" +#include "algebra.h" +#include "secblock.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4127 4189) +#endif + +#include "pkcspad.h" +#include "integer.h" +#include "oaep.h" +#include "dh.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief The LUC function. +/// \details This class is here for historical and pedagogical interest. It has no practical advantages over other +/// trapdoor functions and probably shouldn't be used in production software. The discrete log based LUC schemes +/// defined later in this .h file may be of more practical interest. +/// \since Crypto++ 2.1 +class LUCFunction : public TrapdoorFunction, public PublicKey +{ + typedef LUCFunction ThisClass; + +public: + virtual ~LUCFunction() {} + + /// \brief Initialize a LUC public key with {n,e} + /// \param n the modulus + /// \param e the public exponent + void Initialize(const Integer &n, const Integer &e) + {m_n = n; m_e = e;} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return m_n;} + Integer ImageBound() const {return m_n;} + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // non-derived interface + const Integer & GetModulus() const {return m_n;} + const Integer & GetPublicExponent() const {return m_e;} + + void SetModulus(const Integer &n) {m_n = n;} + void SetPublicExponent(const Integer &e) {m_e = e;} + +protected: + Integer m_n, m_e; +}; + +/// \brief The LUC inverse function. +/// \details This class is here for historical and pedagogical interest. It has no practical advantages over other +/// trapdoor functions and probably shouldn't be used in production software. The discrete log based LUC schemes +/// defined later in this .h file may be of more practical interest. +/// \since Crypto++ 2.1 +class InvertibleLUCFunction : public LUCFunction, public TrapdoorFunctionInverse, public PrivateKey +{ + typedef InvertibleLUCFunction ThisClass; + +public: + virtual ~InvertibleLUCFunction() {} + + /// \brief Create a LUC private key + /// \param rng a RandomNumberGenerator derived class + /// \param modulusBits the size of the modulus, in bits + /// \param eStart the desired starting public exponent + /// \details Initialize() creates a new keypair using a starting public exponent of 17. + /// \details This function overload of Initialize() creates a new keypair because it + /// 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, const Integer &eStart=17); + + /// \brief Initialize a LUC private key with {n,e,p,q,dp,dq,u} + /// \param n modulus + /// \param e public exponent + /// \param p first prime factor + /// \param q second prime factor + /// \param u q-1 mod p + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q, const Integer &u) + {m_n = n; m_e = e; m_p = p; m_q = q; m_u = u;} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + /*! parameters: (ModulusSize, PublicExponent (default 17)) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + // non-derived interface + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} + +protected: + Integer m_p, m_q, m_u; +}; + +/// \brief LUC cryptosystem +/// \since Crypto++ 2.1 +struct LUC +{ + static std::string StaticAlgorithmName() {return "LUC";} + typedef LUCFunction PublicKey; + typedef InvertibleLUCFunction PrivateKey; +}; + +/// \brief LUC encryption scheme +/// \tparam STANDARD signature standard +/// \details This class is here for historical and pedagogical interest. It has no practical advantages over other +/// trapdoor functions and probably shouldn't be used in production software. The discrete log based LUC schemes +/// defined later in this .h file may be of more practical interest. +/// \since Crypto++ 2.1 +template +struct LUCES : public TF_ES +{ +}; + +/// \brief LUC signature scheme with appendix +/// \tparam STANDARD signature standard +/// \tparam H hash transformation +/// \details This class is here for historical and pedagogical interest. It has no practical advantages over other +/// trapdoor functions and probably shouldn't be used in production software. The discrete log based LUC schemes +/// defined later in this .h file may be of more practical interest. +/// \since Crypto++ 2.1 +template +struct LUCSS : public TF_SS +{ +}; + +// analogous to the RSA schemes defined in PKCS #1 v2.0 +typedef LUCES >::Decryptor LUCES_OAEP_SHA_Decryptor; +typedef LUCES >::Encryptor LUCES_OAEP_SHA_Encryptor; + +typedef LUCSS::Signer LUCSSA_PKCS1v15_SHA_Signer; +typedef LUCSS::Verifier LUCSSA_PKCS1v15_SHA_Verifier; + +// ******************************************************** + +/// \brief LUC GroupParameters precomputation +/// \details No actual precomputation is performed +/// \since Crypto++ 2.1 +class DL_GroupPrecomputation_LUC : public DL_GroupPrecomputation +{ +public: + virtual ~DL_GroupPrecomputation_LUC() {} + + const AbstractGroup & GetGroup() const {CRYPTOPP_ASSERT(false); throw 0;} + Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);} + + // non-inherited + void SetModulus(const Integer &v) {m_p = v;} + const Integer & GetModulus() const {return m_p;} + +private: + Integer m_p; +}; + +/// \brief LUC Precomputation +/// \since Crypto++ 2.1 +class DL_BasePrecomputation_LUC : public DL_FixedBasePrecomputation +{ +public: + virtual ~DL_BasePrecomputation_LUC() {} + + // DL_FixedBasePrecomputation + bool IsInitialized() const {return m_g.NotZero();} + void SetBase(const DL_GroupPrecomputation &group, const Integer &base) + {CRYPTOPP_UNUSED(group); m_g = base;} + const Integer & GetBase(const DL_GroupPrecomputation &group) const + {CRYPTOPP_UNUSED(group); return m_g;} + void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) + {CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(maxExpBits); CRYPTOPP_UNUSED(storage);} + void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) + {CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(storedPrecomputation);} + void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const + {CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(storedPrecomputation);} + Integer Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const; + Integer CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const + { + CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(exponent); CRYPTOPP_UNUSED(pc2); CRYPTOPP_UNUSED(exponent2); + // shouldn't be called + throw NotImplemented("DL_BasePrecomputation_LUC: CascadeExponentiate not implemented"); + } + +private: + Integer m_g; +}; + +/// \brief LUC GroupParameters specialization +/// \since Crypto++ 2.1 +class DL_GroupParameters_LUC : public DL_GroupParameters_IntegerBasedImpl +{ +public: + virtual ~DL_GroupParameters_LUC() {} + + // DL_GroupParameters + bool IsIdentity(const Integer &element) const {return element == Integer::Two();} + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + Element MultiplyElements(const Element &a, const Element &b) const + { + CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b); + throw NotImplemented("LUC_GroupParameters: MultiplyElements can not be implemented"); + } + Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const + { + CRYPTOPP_UNUSED(element1); CRYPTOPP_UNUSED(exponent1); CRYPTOPP_UNUSED(element2); CRYPTOPP_UNUSED(exponent2); + throw NotImplemented("LUC_GroupParameters: MultiplyElements can not be implemented"); + } + + // NameValuePairs interface + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper(this, name, valueType, pValue).Assignable(); + } + +private: + int GetFieldType() const {return 2;} +}; + +/// \brief GF(p) group parameters that default to safe primes +/// \since Crypto++ 2.1 +class DL_GroupParameters_LUC_DefaultSafePrime : public DL_GroupParameters_LUC +{ +public: + typedef NoCofactorMultiplication DefaultCofactorOption; + +protected: + unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;} +}; + +/// \brief LUC HMP signature algorithm +/// \since Crypto++ 2.1 +class DL_Algorithm_LUC_HMP : public DL_ElgamalLikeSignatureAlgorithm +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "LUC-HMP";} + + virtual ~DL_Algorithm_LUC_HMP() {} + + void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const; + bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const; + + size_t RLen(const DL_GroupParameters ¶ms) const + {return params.GetGroupOrder().ByteCount();} +}; + +/// \brief LUC signature keys +/// \since Crypto++ 2.1 +struct DL_SignatureKeys_LUC +{ + typedef DL_GroupParameters_LUC GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +/// \brief LUC-HMP, based on "Digital signature schemes based on Lucas functions" by Patrick Horster, Markus Michels, Holger Petersen +/// \tparam H hash transformation +/// \details This class is here for historical and pedagogical interest. It has no practical advantages over other +/// trapdoor functions and probably shouldn't be used in production software. The discrete log based LUC schemes +/// defined later in this .h file may be of more practical interest. +/// \since Crypto++ 2.1 +template +struct LUC_HMP : public DL_SS +{ +}; + +/// \brief LUC encryption keys +/// \since Crypto++ 2.1 +struct DL_CryptoKeys_LUC +{ + typedef DL_GroupParameters_LUC_DefaultSafePrime GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +/// \brief LUC Integrated Encryption Scheme +/// \tparam COFACTOR_OPTION cofactor multiplication option +/// \tparam HASH HashTransformation derived class used for key drivation and MAC computation +/// \tparam DHAES_MODE flag indicating if the MAC includes additional context parameters such as u·V, v·U and label +/// \tparam LABEL_OCTETS flag indicating if the label size is specified in octets or bits +/// \sa CofactorMultiplicationOption +/// \since Crypto++ 2.1, Crypto++ 5.7 for Bouncy Castle and Botan compatibility +template +struct LUC_IES + : public DL_ES< + DL_CryptoKeys_LUC, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE, LABEL_OCTETS>, + LUC_IES<> > +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "LUC-IES";} // non-standard name +}; + +// ******************************************************** + +/// \brief LUC-DH +typedef DH_Domain LUC_DH; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/mars.h b/third_party/cryptoppwin/include/cryptopp/mars.h new file mode 100644 index 00000000..53c093c9 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/mars.h @@ -0,0 +1,60 @@ +// mars.h - originally written and placed in the public domain by Wei Dai + +/// \file mars.h +/// \brief Classes for the MARS block cipher (IBM AES submission) +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_MARS_H +#define CRYPTOPP_MARS_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief MARS block cipher information +/// \since Crypto++ 3.0 +struct MARS_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 56, 8> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "MARS";} +}; + +/// \brief MARS block cipher +/// \sa MARS +/// \since Crypto++ 3.0 +class MARS : public MARS_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + static const word32 Sbox[512]; + + FixedSizeSecBlock m_k; + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef MARS::Encryption MARSEncryption; +typedef MARS::Decryption MARSDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/md2.h b/third_party/cryptoppwin/include/cryptopp/md2.h new file mode 100644 index 00000000..83335d30 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/md2.h @@ -0,0 +1,56 @@ +// md2.h - originally written and placed in the public domain by Wei Dai + +/// \file md2.h +/// \brief Classes for the MD2 message digest +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_MD2_H +#define CRYPTOPP_MD2_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +namespace Weak1 { + +/// \brief MD2 message digest +/// \sa MD2 +/// \since Crypto++ 3.0 +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;} + std::string AlgorithmName() const {return StaticAlgorithmName();} + + CRYPTOPP_CONSTANT(DIGESTSIZE = 16); + CRYPTOPP_CONSTANT(BLOCKSIZE = 16); + +private: + void Transform(); + void Init(); + SecByteBlock m_X, m_C, m_buf; + unsigned int m_count; +}; + +} +#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1 +namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak +#else +using namespace Weak1; // import Weak1 into CryptoPP with warning +#ifdef __GNUC__ +#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning." +#else +#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.") +#endif +#endif + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/md4.h b/third_party/cryptoppwin/include/cryptopp/md4.h new file mode 100644 index 00000000..8984b5e0 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/md4.h @@ -0,0 +1,35 @@ +#ifndef CRYPTOPP_MD4_H +#define CRYPTOPP_MD4_H + +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +namespace Weak1 { + +/// MD4 +/*! \warning MD4 is considered insecure, and should not be used + unless you absolutely need it for compatibility. */ +class MD4 : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word32 *digest, const word32 *data); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "MD4";} +}; + +} +#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1 +namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak +#else +using namespace Weak1; // import Weak1 into CryptoPP with warning +#ifdef __GNUC__ +#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning." +#else +#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.") +#endif +#endif + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/md5.h b/third_party/cryptoppwin/include/cryptopp/md5.h new file mode 100644 index 00000000..2b3e2c3b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/md5.h @@ -0,0 +1,35 @@ +#ifndef CRYPTOPP_MD5_H +#define CRYPTOPP_MD5_H + +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +namespace Weak1 { + +/// \brief MD5 message digest +/// \sa MD5 +/// \since Crypto++ 1.0 +class MD5 : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word32 *digest, const word32 *data); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "MD5";} +}; + +} +#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1 +namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak +#else +using namespace Weak1; // import Weak1 into CryptoPP with warning +#ifdef __GNUC__ +#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning." +#else +#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.") +#endif +#endif + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/mdc.h b/third_party/cryptoppwin/include/cryptopp/mdc.h new file mode 100644 index 00000000..68d5ab8c --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/mdc.h @@ -0,0 +1,84 @@ +// mdc.h - originally written and placed in the public domain by Wei Dai + +/// \file mdc.h +/// \brief Classes for the MDC message digest + +#ifndef CRYPTOPP_MDC_H +#define CRYPTOPP_MDC_H + +#include "seckey.h" +#include "secblock.h" +#include "misc.h" + +// GCC cast warning +#define HashWordPtr(x) ((HashWordType*)(void*)(x)) +#define ConstHashWordPtr(x) ((const HashWordType*)(const void*)(x)) + +NAMESPACE_BEGIN(CryptoPP) + +/// \tparam B BlockCipher derived class +/// \brief MDC_Info cipher information +template +struct MDC_Info : public FixedBlockSize, public FixedKeyLength +{ + static std::string StaticAlgorithmName() {return std::string("MDC/")+B::StaticAlgorithmName();} +}; + +/// \brief MDC cipher +/// \tparam H HashTransformation derived class +/// \details MDC() is a construction by Peter Gutmann to turn an iterated hash function into a PRF +/// \sa MDC +template +class MDC : public MDC_Info +{ + /// \brief MDC cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public BlockCipherImpl > + { + typedef typename H::HashWordType HashWordType; + + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) + { + CRYPTOPP_UNUSED(params); + this->AssertValidKeyLength(length); + ConditionalByteReverse(BIG_ENDIAN_ORDER, Key(), ConstHashWordPtr(userKey), this->KEYLENGTH); + } + + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const + { + ConditionalByteReverse(BIG_ENDIAN_ORDER, Buffer(), ConstHashWordPtr(inBlock), this->BLOCKSIZE); + H::Transform(Buffer(), Key()); + + if (xorBlock) + { + ConditionalByteReverse(BIG_ENDIAN_ORDER, Buffer(), Buffer(), this->BLOCKSIZE); + xorbuf(outBlock, xorBlock, m_buffer, this->BLOCKSIZE); + } + else + { + ConditionalByteReverse(BIG_ENDIAN_ORDER, HashWordPtr(outBlock), Buffer(), this->BLOCKSIZE); + } + } + + bool IsPermutation() const {return false;} + + unsigned int OptimalDataAlignment() const {return sizeof(HashWordType);} + + private: + HashWordType *Key() {return HashWordPtr(m_key.data());} + const HashWordType *Key() const {return ConstHashWordPtr(m_key.data());} + HashWordType *Buffer() const {return HashWordPtr(m_buffer.data());} + + // VC60 workaround: bug triggered if using FixedSizeAllocatorWithCleanup + FixedSizeSecBlock::KEYLENGTH, AllocatorWithCleanup > m_key; + mutable FixedSizeSecBlock::BLOCKSIZE, AllocatorWithCleanup > m_buffer; + }; + +public: + // use BlockCipher interface + typedef BlockCipherFinal Encryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/mersenne.h b/third_party/cryptoppwin/include/cryptopp/mersenne.h new file mode 100644 index 00000000..326d9116 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/mersenne.h @@ -0,0 +1,231 @@ +// mersenne.h - written and placed in public domain by Jeffrey Walton. + +/// \file mersenne.h +/// \brief Class file for Mersenne Twister +/// \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 + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Mersenne Twister class for Monte-Carlo simulations +/// \tparam K Magic constant +/// \tparam M Period parameter +/// \tparam N Size of the state vector +/// \tparam F Multiplier constant +/// \tparam S Initial seed +/// \details Provides the MersenneTwister implementation. The class is a header-only implementation. +/// \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 +class MersenneTwister : public RandomNumberGenerator +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return (S==5489 ? "MT19937ar" : (S==4537 ? "MT19937" : "MT19937x")); } + + ~MersenneTwister() {} + + /// \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_idx(N) + { + Reset(seed); + } + + bool CanIncorporateEntropy() const {return true;} + + /// \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 + /// \details MersenneTwister uses the first 32-bits of input to reseed the + /// generator. If fewer bytes are provided, then the seed is padded with 0's. + void IncorporateEntropy(const byte *input, size_t length) + { + // Handle word32 size blocks + FixedSizeSecBlock temp; + temp[0] = 0; + + if (length > 4) + length = 4; + + for (size_t i=0; i temp; + for (size_t i=0; i < size/4; i++, output += 4) + { + temp[0] = NextMersenneWord(); + std::memcpy(output, temp+0, 4); + } + + // No tail bytes + if (size%4 == 0) + return; + + // Handle tail bytes + temp[0] = NextMersenneWord(); + switch (size%4) + { + 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);; + } + } + + /// \brief Generate a 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. + word32 GenerateWord32(word32 min=0, word32 max=0xffffffffL) + { + const word32 range = max-min; + if (range == 0xffffffffL) + return NextMersenneWord(); + + const int maxBits = BitPrecision(range); + word32 value; + + do{ + value = Crop(NextMersenneWord(), maxBits); + } while (value > range); + + return value+min; + } + + /// \brief Generate and discard n bytes + /// \param n the number of bytes to discard, rounded up to a word32 size + /// \details If n 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 DiscardBytes(size_t n) + { + for(size_t i=0; i < RoundUpToMultipleOf(n, 4U); i++) + NextMersenneWord(); + } + +protected: + + void Reset(word32 seed) + { + m_idx = N; + + m_state[0] = seed; + for (unsigned int i = 1; i < N+1; i++) + m_state[i] = word32(F * (m_state[i-1] ^ (m_state[i-1] >> 30)) + i); + } + + /// \brief 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. + word32 NextMersenneWord() + { + if (m_idx >= N) { Twist(); } + + word32 temp = m_state[m_idx++]; + + temp ^= (temp >> 11); + temp ^= (temp << 7) & 0x9D2C5680; // 0x9D2C5680 (2636928640) + temp ^= (temp << 15) & 0xEFC60000; // 0xEFC60000 (4022730752) + + return temp ^ (temp >> 18); + } + + /// \brief Performs the twist operation on the state array + void Twist() + { + static const word32 magic[2]={0x0UL, K}; + word32 kk, temp; + + CRYPTOPP_ASSERT(N >= M); + for (kk=0;kk> 1) ^ magic[temp & 0x1UL]; + } + + for (;kk> 1) ^ magic[temp & 0x1UL]; + } + + temp = (m_state[N-1] & 0x80000000)|(m_state[0] & 0x7FFFFFFF); + m_state[N-1] = m_state[M-1] ^ (temp >> 1) ^ magic[temp & 0x1UL]; + + // Reset index + m_idx = 0; + + // Wipe temp + SecureWipeArray(&temp, 1); + } + +private: + + /// \brief 32-bit word state array of size N + FixedSizeSecBlock m_state; + /// \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, Mersenne twister: +/// a 623-dimensionally equidistributed uniform pseudo-random number generator +/// \since Crypto++ 5.6.3 +#if CRYPTOPP_DOXYGEN_PROCESSING +class MT19937 : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> {}; +#else +typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> MT19937; +#endif + +/// \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. +/// \details You should reseed the generator after a fork() to avoid multiple generators +/// with the same internal state. +/// \sa MT19937, Mersenne Twister +/// with improved initialization +/// \since Crypto++ 5.6.3 +#if CRYPTOPP_DOXYGEN_PROCESSING +class MT19937ar : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> {}; +#else +typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> MT19937ar; +#endif + +NAMESPACE_END + +#endif // CRYPTOPP_MERSENNE_TWISTER_H diff --git a/third_party/cryptoppwin/include/cryptopp/misc.h b/third_party/cryptoppwin/include/cryptopp/misc.h new file mode 100644 index 00000000..2e2bd5a5 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/misc.h @@ -0,0 +1,3222 @@ +// misc.h - originally written and placed in the public domain by Wei Dai + +/// \file misc.h +/// \brief Utility functions for the Crypto++ library. + +#ifndef CRYPTOPP_MISC_H +#define CRYPTOPP_MISC_H + +#include "config.h" + +#include "cryptlib.h" +#include "secblockfwd.h" +#include "smartptr.h" +#include "stdcpp.h" +#include "trap.h" + +#if !defined(CRYPTOPP_DOXYGEN_PROCESSING) + +#if (CRYPTOPP_MSC_VERSION) +# pragma warning(push) +# pragma warning(disable: 4146 4514) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6326) +# endif +#endif + +// Issue 340 and Issue 793 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wsign-conversion" +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#ifdef CRYPTOPP_MSC_VERSION + #if CRYPTOPP_MSC_VERSION >= 1400 + // VC2005 workaround: disable declarations that conflict with winnt.h + #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1 + #define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2 + #define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3 + #define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4 + #include + #undef _interlockedbittestandset + #undef _interlockedbittestandreset + #undef _interlockedbittestandset64 + #undef _interlockedbittestandreset64 + #define CRYPTOPP_FAST_ROTATE(x) 1 + #elif CRYPTOPP_MSC_VERSION >= 1300 + #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64) + #else + #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) + #endif +#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \ + (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM))) + #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) +#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions + #define CRYPTOPP_FAST_ROTATE(x) 1 +#else + #define CRYPTOPP_FAST_ROTATE(x) 0 +#endif + +#ifdef __BORLANDC__ +#include +#include +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && defined(__linux__) +#define CRYPTOPP_BYTESWAP_AVAILABLE 1 +#include +#endif + +// Limit to ARM A-32. Aarch64 is failing self tests. +#if defined(__arm__) && (defined(__GNUC__) || defined(__clang__)) && (__ARM_ARCH >= 6) +#define CRYPTOPP_ARM_BYTEREV_AVAILABLE 1 +#endif + +// Limit to ARM A-32. Aarch64 is failing self tests. +#if defined(__arm__) && (defined(__GNUC__) || defined(__clang__)) && (__ARM_ARCH >= 7) +#define CRYPTOPP_ARM_BITREV_AVAILABLE 1 +#endif + +#if defined(__BMI__) +# if defined(CRYPTOPP_GCC_COMPATIBLE) +# include +# endif +# include +#endif // BMI + +// More LLVM bullshit. Apple Clang 6.0 does not define them. +// Later version of Clang defines them and results in warnings. +#if defined(__clang__) +# ifndef _blsr_u32 +# define _blsr_u32 __blsr_u32 +# endif +# ifndef _blsr_u64 +# define _blsr_u64 __blsr_u64 +# endif +# ifndef _tzcnt_u32 +# define _tzcnt_u32 __tzcnt_u32 +# endif +# ifndef _tzcnt_u64 +# define _tzcnt_u64 __tzcnt_u64 +# endif +#endif + +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +#if CRYPTOPP_DOXYGEN_PROCESSING +/// \brief The maximum value of a machine word +/// \details SIZE_MAX provides the maximum value of a machine word. The value +/// is 0xffffffff on 32-bit targets, and 0xffffffffffffffff on 64-bit +/// targets. +/// \details If SIZE_MAX is not defined, then __SIZE_MAX__ is used if +/// defined. If not defined, then SIZE_T_MAX is used if defined. If not defined, +/// then the library uses std::numeric_limits::max(). +/// \details The library prefers __SIZE_MAX__ or __SIZE_T_MAX__ because +/// they are effectively constexpr that is optimized well by all compilers. +/// std::numeric_limits::max() is not always a constexpr, and +/// it is not always optimized well. +# define SIZE_MAX ... +#else +// Its amazing portability problems still plague this simple concept in 2015. +// http://stackoverflow.com/questions/30472731/which-c-standard-header-defines-size-max +// Avoid NOMINMAX macro on Windows. http://support.microsoft.com/en-us/kb/143208 +#ifndef SIZE_MAX +# if defined(__SIZE_MAX__) +# define SIZE_MAX __SIZE_MAX__ +# elif defined(SIZE_T_MAX) +# define SIZE_MAX SIZE_T_MAX +# elif defined(__SIZE_TYPE__) +# define SIZE_MAX (~(__SIZE_TYPE__)0) +# else +# define SIZE_MAX ((std::numeric_limits::max)()) +# endif +#endif + +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +NAMESPACE_BEGIN(CryptoPP) + +// Forward declaration for IntToString specialization +class Integer; + +// ************** compile-time assertion *************** + +#if CRYPTOPP_DOXYGEN_PROCESSING +/// \brief Compile time assertion +/// \param expr the expression to evaluate +/// \details Asserts the expression expr during compile. If C++14 and +/// N3928 are available, then C++14 static_assert is used. Otherwise, +/// a CompileAssert structure is used. When the structure is used +/// a negative-sized array triggers the assert at compile time. +# define CRYPTOPP_COMPILE_ASSERT(expr) { ... } +#elif defined(CRYPTOPP_CXX17_STATIC_ASSERT) +# define CRYPTOPP_COMPILE_ASSERT(expr) static_assert(expr) +#else // CRYPTOPP_DOXYGEN_PROCESSING +template +struct CompileAssert +{ + static char dummy[2*b-1]; +}; + +#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__) +#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y) +#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y + +#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS) +# define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) +#else +# if defined(__GNUC__) || defined(__clang__) +# define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) \ + static CompileAssert<(assertion)> \ + CRYPTOPP_ASSERT_JOIN(cryptopp_CRYPTOPP_ASSERT_, instance) __attribute__ ((unused)) +# else +# define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) \ + static CompileAssert<(assertion)> \ + CRYPTOPP_ASSERT_JOIN(cryptopp_CRYPTOPP_ASSERT_, instance) +# endif // GCC or Clang +#endif + +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +// ************** count elements in an array *************** + +#if CRYPTOPP_DOXYGEN_PROCESSING +/// \brief Counts elements in an array +/// \param arr an array of elements +/// \details COUNTOF counts elements in an array. On Windows COUNTOF(x) is defined +/// to _countof(x) to ensure correct results for pointers. +/// \note COUNTOF does not produce correct results with pointers, and an array must be used. +/// sizeof(x)/sizeof(x[0]) suffers the same problem. The risk is eliminated by using +/// _countof(x) on Windows. Windows will provide the immunity for other platforms. +# define COUNTOF(arr) +#else +// VS2005 added _countof +#ifndef COUNTOF +# if defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_MSC_VERSION >= 1400) +# define COUNTOF(x) _countof(x) +# else +# define COUNTOF(x) (sizeof(x)/sizeof(x[0])) +# endif +#endif // COUNTOF +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +// ************** misc classes *************** + +/// \brief An Empty class +/// \details The Empty class can be used as a template parameter BASE when no base class exists. +class CRYPTOPP_DLL Empty +{ +}; + +#if !defined(CRYPTOPP_DOXYGEN_PROCESSING) +template +class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2 +{ +}; + +template +class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3 +{ +}; +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +/// \tparam T class or type +/// \brief Uses encapsulation to hide an object in derived classes +/// \details The object T is declared as protected. +template +class ObjectHolder +{ +protected: + T m_object; +}; + +/// \brief Ensures an object is not copyable +/// \details NotCopyable ensures an object is not copyable by making the +/// copy constructor and assignment operator private. Deleters are used +/// under C++11. +/// \sa Clonable class +class NotCopyable +{ +public: + NotCopyable() {} +#if CRYPTOPP_CXX11_DELETED_FUNCTIONS + NotCopyable(const NotCopyable &) = delete; + void operator=(const NotCopyable &) = delete; +#else +private: + NotCopyable(const NotCopyable &); + void operator=(const NotCopyable &); +#endif +}; + +/// \brief An object factory function +/// \tparam T class or type +/// \details NewObject overloads operator()(). +template +struct NewObject +{ + T* operator()() const {return new T;} +}; + +#if CRYPTOPP_DOXYGEN_PROCESSING +/// \brief A memory barrier +/// \details MEMORY_BARRIER attempts to ensure reads and writes are completed +/// in the absence of a language synchronization point. It is used by the +/// Singleton class if the compiler supports it. The barrier is provided at the +/// customary places in a double-checked initialization. +/// \details Internally, MEMORY_BARRIER uses std::atomic_thread_fence if +/// C++11 atomics are available. Otherwise, intrinsic(_ReadWriteBarrier), +/// _ReadWriteBarrier() or __asm__("" ::: "memory") is used. +#define MEMORY_BARRIER ... +#else +#if defined(CRYPTOPP_CXX11_ATOMIC) +# define MEMORY_BARRIER() std::atomic_thread_fence(std::memory_order_acq_rel) +#elif (CRYPTOPP_MSC_VERSION >= 1400) +# pragma intrinsic(_ReadWriteBarrier) +# define MEMORY_BARRIER() _ReadWriteBarrier() +#elif defined(__INTEL_COMPILER) +# define MEMORY_BARRIER() __memory_barrier() +#elif defined(__GNUC__) || defined(__clang__) +# define MEMORY_BARRIER() __asm__ __volatile__ ("" ::: "memory") +#else +# define MEMORY_BARRIER() +#endif +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +/// \brief Restricts the instantiation of a class to one static object without locks +/// \tparam T the class or type +/// \tparam F the object factory for T +/// \tparam instance an instance counter for the class object +/// \details This class safely initializes a static object in a multi-threaded environment. For C++03 +/// and below it will do so without using locks for portability. If two threads call Ref() at the same +/// time, they may get back different references, and one object may end up being memory leaked. This +/// is by design and it avoids a subtle initialization problem in a multi-threaded environment with thread +/// local storage on early Windows platforms, like Windows XP and Windows 2003. +/// \details For C++11 and above, a standard double-checked locking pattern with thread fences +/// are used. The locks and fences are standard and do not hinder portability. +/// \details Microsoft's C++11 implementation provides the necessary primitive support on Windows Vista and +/// above when using Visual Studio 2015 (cl.exe version 19.00). If C++11 is desired, you should +/// set WINVER or _WIN32_WINNT to 0x600 (or above), and compile with Visual Studio 2015. +/// \sa Double-Checked Locking +/// is Fixed In C++11, Dynamic +/// Initialization and Destruction with Concurrency and +/// Thread Local Storage (TLS) on MSDN. +/// \since Crypto++ 5.2 +template , int instance=0> +class Singleton +{ +public: + Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} + + // prevent this function from being inlined + CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const; + +private: + F m_objectFactory; +}; + +/// \brief Return a reference to the inner Singleton object +/// \tparam T the class or type +/// \tparam F the object factory for T +/// \tparam instance an instance counter for the class object +/// \details Ref() is used to create the object using the object factory. The +/// object is only created once with the limitations discussed in the class documentation. +/// \sa Double-Checked Locking is Fixed In C++11 +/// \since Crypto++ 5.2 +template + const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const +{ +#if defined(CRYPTOPP_CXX11_ATOMIC) && defined(CRYPTOPP_CXX11_SYNCHRONIZATION) && defined(CRYPTOPP_CXX11_STATIC_INIT) + static std::mutex s_mutex; + static std::atomic s_pObject; + + T *p = s_pObject.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); + + if (p) + return *p; + + std::lock_guard lock(s_mutex); + p = s_pObject.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); + + if (p) + return *p; + + T *newObject = m_objectFactory(); + std::atomic_thread_fence(std::memory_order_release); + s_pObject.store(newObject, std::memory_order_relaxed); + + return *newObject; +#else + static volatile simple_ptr s_pObject; + T *p = s_pObject.m_p; + MEMORY_BARRIER(); + + if (p) + return *p; + + T *newObject = m_objectFactory(); + p = s_pObject.m_p; + MEMORY_BARRIER(); + + if (p) + { + delete newObject; + return *p; + } + + s_pObject.m_p = newObject; + MEMORY_BARRIER(); + + return *newObject; +#endif +} + +// ************** misc functions *************** + +/// \brief Create a pointer with an offset +/// \tparam PTR a pointer type +/// \tparam OFF a size type +/// \param pointer a pointer +/// \param offset a offset into the pointer +/// \details PtrAdd can be used to squash Clang and GCC +/// UBsan findings for pointer addition and subtraction. +template +inline PTR PtrAdd(PTR pointer, OFF offset) +{ + return pointer+static_cast(offset); +} + +/// \brief Create a pointer with an offset +/// \tparam PTR a pointer type +/// \tparam OFF a size type +/// \param pointer a pointer +/// \param offset a offset into the pointer +/// \details PtrSub can be used to squash Clang and GCC +/// UBsan findings for pointer addition and subtraction. +template +inline PTR PtrSub(PTR pointer, OFF offset) +{ + return pointer-static_cast(offset); +} + +/// \brief Determine pointer difference +/// \tparam PTR a pointer type +/// \param pointer1 the first pointer +/// \param pointer2 the second pointer +/// \details PtrDiff can be used to squash Clang and GCC +/// UBsan findings for pointer addition and subtraction. +/// pointer1 and pointer2 must point to the same object or +/// array (or one past the end), and yields the number of +/// elements (not bytes) difference. +template +inline ptrdiff_t PtrDiff(const PTR pointer1, const PTR pointer2) +{ + return pointer1 - pointer2; +} + +/// \brief Determine pointer difference +/// \tparam PTR a pointer type +/// \param pointer1 the first pointer +/// \param pointer2 the second pointer +/// \details PtrByteDiff can be used to squash Clang and GCC +/// UBsan findings for pointer addition and subtraction. +/// pointer1 and pointer2 must point to the same object or +/// array (or one past the end), and yields the number of +/// bytes (not elements) difference. +template +inline size_t PtrByteDiff(const PTR pointer1, const PTR pointer2) +{ + return (size_t)(reinterpret_cast(pointer1) - reinterpret_cast(pointer2)); +} + +/// \brief Pointer to the first element of a string +/// \param str string +/// \details BytePtr returns NULL pointer for an empty string. +/// \return Pointer to the first element of a string +/// \since Crypto++ 8.0 +inline byte* BytePtr(std::string& str) +{ + // Caller wants a writable pointer + CRYPTOPP_ASSERT(str.empty() == false); + + if (str.empty()) + return NULLPTR; + return reinterpret_cast(&str[0]); +} + +/// \brief Pointer to the first element of a string +/// \param str SecByteBlock +/// \details BytePtr returns NULL pointer for an empty string. +/// \return Pointer to the first element of a string +/// \since Crypto++ 8.3 +byte* BytePtr(SecByteBlock& str); + +/// \brief Const pointer to the first element of a string +/// \param str string +/// \details ConstBytePtr returns non-NULL pointer for an empty string. +/// \return Pointer to the first element of a string +/// \since Crypto++ 8.0 +inline const byte* ConstBytePtr(const std::string& str) +{ + if (str.empty()) + return NULLPTR; + return reinterpret_cast(&str[0]); +} + +/// \brief Const pointer to the first element of a string +/// \param str SecByteBlock +/// \details ConstBytePtr returns non-NULL pointer for an empty string. +/// \return Pointer to the first element of a string +/// \since Crypto++ 8.3 +const byte* ConstBytePtr(const SecByteBlock& str); + +/// \brief Size of a string +/// \param str string +/// \return size of a string +/// \since Crypto++ 8.3 +inline size_t BytePtrSize(const std::string& str) +{ + return str.size(); +} + +/// \brief Size of a string +/// \param str SecByteBlock +/// \return size of a string +/// \since Crypto++ 8.3 +size_t BytePtrSize(const SecByteBlock& str); + +/// \brief Integer value +/// \details EnumToInt avoids C++20 enum-enum conversion +/// warnings under GCC and Clang. C++11 and above use a +/// constexpr function. C++03 and below use a macro due +/// to [lack of] constexpr-ness in early versions of C++. +/// \since Crypto++ 8.6 +#if (CRYPTOPP_CXX11_CONSTEXPR) +template +constexpr int EnumToInt(T v) { + return static_cast(v); +} +#else +# define EnumToInt(v) static_cast(v) +#endif + +#if (!__STDC_WANT_SECURE_LIB__ && !defined(_MEMORY_S_DEFINED)) || defined(CRYPTOPP_WANT_SECURE_LIB) + +/// \brief Bounds checking replacement for memcpy() +/// \param dest pointer to the destination memory block +/// \param sizeInBytes size of the destination memory block, in bytes +/// \param src pointer to the source memory block +/// \param count the number of bytes to copy +/// \throw InvalidArgument +/// \details ISO/IEC TR-24772 provides bounds checking interfaces for potentially +/// unsafe functions like memcpy(), strcpy() and memmove(). However, +/// not all standard libraries provides them, like Glibc. The library's +/// memcpy_s() is a near-drop in replacement. Its only a near-replacement +/// because the library's version throws an InvalidArgument on a bounds violation. +/// \details memcpy_s() and memmove_s() are guarded by __STDC_WANT_SECURE_LIB__. +/// If __STDC_WANT_SECURE_LIB__ is not defined or defined to 0, then the library +/// makes memcpy_s() and memmove_s() available. The library will also optionally +/// make the symbols available if CRYPTOPP_WANT_SECURE_LIB is defined. +/// CRYPTOPP_WANT_SECURE_LIB is in config.h, but it is disabled by default. +/// \details memcpy_s() will assert the pointers src and dest are not NULL +/// in debug builds. Passing NULL for either pointer is undefined behavior. +inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count) +{ + // Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55 + + // Pointers must be valid; otherwise undefined behavior + CRYPTOPP_ASSERT(dest != NULLPTR); CRYPTOPP_ASSERT(src != NULLPTR); + // Restricted pointers. We want to check ranges, but it is not clear how to do it. + CRYPTOPP_ASSERT(src != dest); + // Destination buffer must be large enough to satisfy request + CRYPTOPP_ASSERT(sizeInBytes >= count); + + if (count > sizeInBytes) + throw InvalidArgument("memcpy_s: buffer overflow"); + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4996) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6386) +# endif +#endif + if (src != NULLPTR && dest != NULLPTR) + std::memcpy(dest, src, count); +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif +} + +/// \brief Bounds checking replacement for memmove() +/// \param dest pointer to the destination memory block +/// \param sizeInBytes size of the destination memory block, in bytes +/// \param src pointer to the source memory block +/// \param count the number of bytes to copy +/// \throw InvalidArgument +/// \details ISO/IEC TR-24772 provides bounds checking interfaces for potentially +/// unsafe functions like memcpy(), strcpy() and memmove(). However, +/// not all standard libraries provides them, like Glibc. The library's +/// memmove_s() is a near-drop in replacement. Its only a near-replacement +/// because the library's version throws an InvalidArgument on a bounds violation. +/// \details memcpy_s() and memmove_s() are guarded by __STDC_WANT_SECURE_LIB__. +/// If __STDC_WANT_SECURE_LIB__ is not defined or defined to 0, then the library +/// makes memcpy_s() and memmove_s() available. The library will also optionally +/// make the symbols available if CRYPTOPP_WANT_SECURE_LIB is defined. +/// CRYPTOPP_WANT_SECURE_LIB is in config.h, but it is disabled by default. +/// \details memmove_s() will assert the pointers src and dest are not NULL +/// in debug builds. Passing NULL for either pointer is undefined behavior. +inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count) +{ + // Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55 + + // Pointers must be valid; otherwise undefined behavior + CRYPTOPP_ASSERT(dest != NULLPTR); CRYPTOPP_ASSERT(src != NULLPTR); + // Destination buffer must be large enough to satisfy request + CRYPTOPP_ASSERT(sizeInBytes >= count); + + if (count > sizeInBytes) + throw InvalidArgument("memmove_s: buffer overflow"); + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4996) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6386) +# endif +#endif + if (src != NULLPTR && dest != NULLPTR) + std::memmove(dest, src, count); +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif +} + +#if __BORLANDC__ >= 0x620 +// C++Builder 2010 workaround: can't use memcpy_s +// because it doesn't allow 0 lengths +# define memcpy_s CryptoPP::memcpy_s +# define memmove_s CryptoPP::memmove_s +#endif + +#endif // __STDC_WANT_SECURE_LIB__ + +/// \brief Swaps two variables which are arrays +/// \tparam T class or type +/// \param a the first value +/// \param b the second value +/// \details C++03 does not provide support for std::swap(__m128i a, __m128i b) +/// because __m128i is an unsigned long long[2]. Most compilers +/// support it out of the box, but Sun Studio C++ compilers 12.2 and 12.3 do not. +/// \sa How to swap two __m128i variables +/// in C++03 given its an opaque type and an array? on Stack Overflow. +template +inline void vec_swap(T& a, T& b) +{ + // __m128i is an unsigned long long[2], and support for swapping it was + // not added until C++11. SunCC 12.1 - 12.3 fail to consume the swap; while + // SunCC 12.4 consumes it without -std=c++11. +#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x5120) + T t; + t=a, a=b, b=t; +#else + std::swap(a, b); +#endif +} + +/// \brief Memory block initializer +/// \param ptr pointer to the memory block being written +/// \param val the integer value to write for each byte +/// \param num the size of the source memory block, in bytes +/// \details Internally the function calls memset with the value val. +/// memset_z can be used to initialize a freshly allocated memory block. +/// To zeroize a memory block on destruction use SecureWipeBuffer. +/// \return the pointer to the memory block +/// \sa SecureWipeBuffer +inline void * memset_z(void *ptr, int val, size_t num) +{ +// avoid extraneous warning on GCC 4.3.2 Ubuntu 8.10 +#if CRYPTOPP_GCC_VERSION >= 30001 || CRYPTOPP_LLVM_CLANG_VERSION >= 20800 || \ + CRYPTOPP_APPLE_CLANG_VERSION >= 30000 + if (__builtin_constant_p(num) && num==0) + return ptr; +#endif + return std::memset(ptr, val, num); +} + +/// \brief Replacement function for std::min +/// \tparam T class or type +/// \param a the first value +/// \param b the second value +/// \return the minimum value based on a comparison of b \< a using operator\< +/// \details STDMIN was provided because the library could not easily use std::min or std::max in Windows or Cygwin 1.1.0 +template inline const T& STDMIN(const T& a, const T& b) +{ + return b < a ? b : a; +} + +/// \brief Replacement function for std::max +/// \tparam T class or type +/// \param a the first value +/// \param b the second value +/// \return the minimum value based on a comparison of a \< b using operator\< +/// \details STDMAX was provided because the library could not easily use std::min or std::max in Windows or Cygwin 1.1.0 +template inline const T& STDMAX(const T& a, const T& b) +{ + return a < b ? b : a; +} + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4389) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wstrict-overflow" +# if (CRYPTOPP_LLVM_CLANG_VERSION >= 20800) || (CRYPTOPP_APPLE_CLANG_VERSION >= 30000) +# pragma GCC diagnostic ignored "-Wtautological-compare" +# elif (CRYPTOPP_GCC_VERSION >= 40300) +# pragma GCC diagnostic ignored "-Wtype-limits" +# endif +#endif + +/// \brief Safe comparison of values that could be negative and incorrectly promoted +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param a the first value +/// \param b the second value +/// \return the minimum value based on a comparison a and b using operator<. +/// \details The comparison b \< a is performed and the value returned is type T1. +template inline const T1 UnsignedMin(const T1& a, const T2& b) +{ + CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0)); + CRYPTOPP_COMPILE_ASSERT(std::numeric_limits::is_signed == false); + CRYPTOPP_COMPILE_ASSERT(std::numeric_limits::is_signed == false); + + if (sizeof(T1)<=sizeof(T2)) + return b < (T2)a ? (T1)b : a; + else + return (T1)b < a ? (T1)b : a; +} + +/// \brief Perform a conversion from \p from to \p to +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function returns false, +/// then \p to is undefined and should not be used. +/// \note for integral conversions, a template specialization should be provided. The specialization +/// will perform more efficiently, and avoid warnings for truncation and sign compares. +template +inline bool SafeConvert(T1 from, T2 &to) +{ + to = static_cast(from); + if (from != to || (from > 0) != (to > 0)) + return false; + return true; +} + +// The following specializations are the product of {word32, sword32, word64, sword64} -> +// {word32, sword32, word64, sword64}. There are 16 of them, but we can omit specializations +// of {word64} -> {word64}, {word32} -> {word32}, etc. +// +// The list below proceeds to list the conversion to word64 (3 each), followed by +// sword64 (3 each), followed by word32 (3 each), and finally follwed by sword32 (3 each). + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(sword64 from, word64 &to) +{ + if (from < 0) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(word32 from, word64 &to) +{ + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(sword32 from, word64 &to) +{ + if (from < 0) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(word64 from, sword64 &to) +{ + if (from > static_cast((std::numeric_limits::max)())) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(word32 from, sword64 &to) +{ + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(sword32 from, sword64 &to) +{ + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(word64 from, word32 &to) +{ + if (from > static_cast((std::numeric_limits::max)())) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(sword64 from, word32 &to) +{ + if (from < 0) + return false; + else if (from > static_cast((std::numeric_limits::max)())) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(sword32 from, word32 &to) +{ + if (from < 0) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(word64 from, sword32 &to) +{ + if (from > static_cast((std::numeric_limits::max)())) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(sword64 from, sword32 &to) +{ + if (from > static_cast((std::numeric_limits::max)())) + return false; + else if (from < static_cast((std::numeric_limits::min)())) + return false; + to = static_cast(from); + return true; +} + +/// \brief Perform a conversion from \p from to \p to +/// \param from the first value +/// \param to the second value +/// \return true if its safe to convert from \p from to \p to, false otherwise. +/// \details if the function returns true, then it is safe to use \p to. If the function +/// returns false, then \p to is undefined and should not be used. +/// \since Crypto++ 8.8 +template<> +inline bool SafeConvert(word32 from, sword32 &to) +{ + if (from > static_cast((std::numeric_limits::max)())) + return false; + to = static_cast(from); + return true; +} + +/// \brief Converts a value to a string +/// \tparam T class or type +/// \param value the value to convert +/// \param base the base to use during the conversion +/// \return the string representation of value in base. +template +std::string IntToString(T value, unsigned int base = 10) +{ + // Hack... set the high bit for uppercase. + const unsigned int HIGH_BIT = (1U << 31); + const char CH = !!(base & HIGH_BIT) ? 'A' : 'a'; + base &= ~HIGH_BIT; + + CRYPTOPP_ASSERT(base >= 2); + if (value == 0) + return "0"; + + bool negate = false; + if (value < 0) + { + negate = true; + value = 0-value; // VC .NET does not like -a + } + std::string result; + while (value > 0) + { + T digit = value % base; + result = char((digit < 10 ? '0' : (CH - 10)) + digit) + result; + value /= base; + } + if (negate) + result = "-" + result; + return result; +} + +/// \brief Converts an unsigned value to a string +/// \param value the value to convert +/// \param base the base to use during the conversion +/// \return the string representation of value in base. +/// \details this template function specialization was added to suppress +/// Coverity findings on IntToString() with unsigned types. +template <> CRYPTOPP_DLL +std::string IntToString(word64 value, unsigned int base); + +/// \brief Converts an Integer to a string +/// \param value the Integer to convert +/// \param base the base to use during the conversion +/// \return the string representation of value in base. +/// \details This is a template specialization of IntToString(). Use it +/// like IntToString(): +///
+///  // Print integer in base 10
+///  Integer n...
+///  std::string s = IntToString(n, 10);
+/// 
+/// \details The string is presented with lowercase letters by default. A +/// hack is available to switch to uppercase letters without modifying +/// the function signature. +///
+///  // Print integer in base 16, uppercase letters
+///  Integer n...
+///  const unsigned int UPPER = (1 << 31);
+///  std::string s = IntToString(n, (UPPER | 16));
+template <> CRYPTOPP_DLL +std::string IntToString(Integer value, unsigned int base); + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif + +#define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue + +// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack +#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y))) +// these may be faster on other CPUs/compilers +// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255) +// #define GETBYTE(x, y) (((byte *)&(x))[y]) + +#define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y))) + +/// \brief Returns the parity of a value +/// \tparam T class or type +/// \param value the value to provide the parity +/// \return 1 if the number 1-bits in the value is odd, 0 otherwise +template +unsigned int Parity(T value) +{ + for (unsigned int i=8*sizeof(value)/2; i>0; i/=2) + value ^= value >> i; + return (unsigned int)value&1; +} + +/// \brief Returns the number of 8-bit bytes or octets required for a value +/// \tparam T class or type +/// \param value the value to test +/// \return the minimum number of 8-bit bytes or octets required to represent a value +template +unsigned int BytePrecision(const T &value) +{ + if (!value) + return 0; + + unsigned int l=0, h=8*sizeof(value); + while (h-l > 8) + { + unsigned int t = (l+h)/2; + if (value >> t) + l = t; + else + h = t; + } + + return h/8; +} + +/// \brief Returns the number of bits required for a value +/// \tparam T class or type +/// \param value the value to test +/// \return the maximum number of bits required to represent a value. +template +unsigned int BitPrecision(const T &value) +{ + if (!value) + return 0; + + unsigned int l=0, h=8*sizeof(value); + + while (h-l > 1) + { + unsigned int t = (l+h)/2; + if (value >> t) + l = t; + else + h = t; + } + + return h; +} + +/// Determines the number of trailing 0-bits in a value +/// \param v the 32-bit value to test +/// \return the number of trailing 0-bits in v, starting at the least significant bit position +/// \details TrailingZeros returns the number of trailing 0-bits in v, starting at the least +/// significant bit position. The return value is undefined if there are no 1-bits set in the value v. +/// \note The function does not return 0 if no 1-bits are set because 0 collides with a 1-bit at the 0-th position. +inline unsigned int TrailingZeros(word32 v) +{ + // GCC 4.7 and VS2012 provides tzcnt on AVX2/BMI enabled processors + // We don't enable for Microsoft because it requires a runtime check. + // http://msdn.microsoft.com/en-us/library/hh977023%28v=vs.110%29.aspx + CRYPTOPP_ASSERT(v != 0); +#if defined(__BMI__) + return (unsigned int)_tzcnt_u32(v); +#elif defined(__GNUC__) && (CRYPTOPP_GCC_VERSION >= 30400) + return (unsigned int)__builtin_ctz(v); +#elif defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_MSC_VERSION >= 1400) + unsigned long result; + _BitScanForward(&result, v); + return static_cast(result); +#else + // from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup + static const int MultiplyDeBruijnBitPosition[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27]; +#endif +} + +/// Determines the number of trailing 0-bits in a value +/// \param v the 64-bit value to test +/// \return the number of trailing 0-bits in v, starting at the least significant bit position +/// \details TrailingZeros returns the number of trailing 0-bits in v, starting at the least +/// significant bit position. The return value is undefined if there are no 1-bits set in the value v. +/// \note The function does not return 0 if no 1-bits are set because 0 collides with a 1-bit at the 0-th position. +inline unsigned int TrailingZeros(word64 v) +{ + // GCC 4.7 and VS2012 provides tzcnt on AVX2/BMI enabled processors + // We don't enable for Microsoft because it requires a runtime check. + // http://msdn.microsoft.com/en-us/library/hh977023%28v=vs.110%29.aspx + CRYPTOPP_ASSERT(v != 0); +#if defined(__BMI__) && defined(__x86_64__) + return (unsigned int)_tzcnt_u64(v); +#elif defined(__GNUC__) && (CRYPTOPP_GCC_VERSION >= 30400) + return (unsigned int)__builtin_ctzll(v); +#elif defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_MSC_VERSION >= 1400) && (defined(_M_X64) || defined(_M_IA64)) + unsigned long result; + _BitScanForward64(&result, v); + return static_cast(result); +#else + return word32(v) ? TrailingZeros(word32(v)) : 32 + TrailingZeros(word32(v>>32)); +#endif +} + +/// \brief Truncates the value to the specified number of bits. +/// \tparam T class or type +/// \param value the value to truncate or mask +/// \param bits the number of bits to truncate or mask +/// \return the value truncated to the specified number of bits, starting at the least +/// significant bit position +/// \details This function masks the low-order bits of value and returns the result. The +/// mask is created with (1 << bits) - 1. +template +inline T Crop(T value, size_t bits) +{ + if (bits < 8*sizeof(value)) + return T(value & ((T(1) << bits) - 1)); + else + return value; +} + +/// \brief Returns the number of 8-bit bytes or octets required for the specified number of bits +/// \param bitCount the number of bits +/// \return the minimum number of 8-bit bytes or octets required by bitCount +/// \details BitsToBytes is effectively a ceiling function based on 8-bit bytes. +inline size_t BitsToBytes(size_t bitCount) +{ + return ((bitCount+7)/(8)); +} + +/// \brief Returns the number of words required for the specified number of bytes +/// \param byteCount the number of bytes +/// \return the minimum number of words required by byteCount +/// \details BytesToWords is effectively a ceiling function based on WORD_SIZE. +/// WORD_SIZE is defined in config.h +inline size_t BytesToWords(size_t byteCount) +{ + return ((byteCount+WORD_SIZE-1)/WORD_SIZE); +} + +/// \brief Returns the number of words required for the specified number of bits +/// \param bitCount the number of bits +/// \return the minimum number of words required by bitCount +/// \details BitsToWords is effectively a ceiling function based on WORD_BITS. +/// WORD_BITS is defined in config.h +inline size_t BitsToWords(size_t bitCount) +{ + return ((bitCount+WORD_BITS-1)/(WORD_BITS)); +} + +/// \brief Returns the number of double words required for the specified number of bits +/// \param bitCount the number of bits +/// \return the minimum number of double words required by bitCount +/// \details BitsToDwords is effectively a ceiling function based on 2*WORD_BITS. +/// WORD_BITS is defined in config.h +inline size_t BitsToDwords(size_t bitCount) +{ + return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS)); +} + +/// Performs an XOR of a buffer with a mask +/// \param buf the buffer to XOR with the mask +/// \param mask the mask to XOR with the buffer +/// \param count the size of the buffers, in bytes +/// \details The function effectively visits each element in the buffers and performs +/// buf[i] ^= mask[i]. buf and mask must be of equal size. +CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count); + +/// Performs an XOR of an input buffer with a mask and stores the result in an output buffer +/// \param output the destination buffer +/// \param input the source buffer to XOR with the mask +/// \param mask the mask buffer to XOR with the input buffer +/// \param count the size of the buffers, in bytes +/// \details The function effectively visits each element in the buffers and performs +/// output[i] = input[i] ^ mask[i]. output, input and mask must be of equal size. +CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count); + +/// \brief Performs a near constant-time comparison of two equally sized buffers +/// \param buf1 the first buffer +/// \param buf2 the second buffer +/// \param count the size of the buffers, in bytes +/// \details VerifyBufsEqual performs an XOR of the elements in two equally sized +/// buffers and returns a result based on the XOR operation. A count of 0 returns +/// true because two empty buffers are considered equal. +/// \details The function is near constant-time because CPU micro-code timings could +/// affect the "constant-ness". Calling code is responsible for mitigating timing +/// attacks if the buffers are not equally sized. +/// \sa ModPowerOf2 +CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count); + +/// \brief Tests whether a value is a power of 2 +/// \param value the value to test +/// \return true if value is a power of 2, false otherwise +/// \details The function creates a mask of value - 1 and returns the result +/// of an AND operation compared to 0. If value is 0 or less than 0, then the function +/// returns false. +template +inline bool IsPowerOf2(const T &value) +{ + return value > 0 && (value & (value-1)) == 0; +} + +#if defined(__BMI__) +template <> +inline bool IsPowerOf2(const word32 &value) +{ + return value > 0 && _blsr_u32(value) == 0; +} + +# if defined(__x86_64__) +template <> +inline bool IsPowerOf2(const word64 &value) +{ + return value > 0 && _blsr_u64(value) == 0; +} +# endif // __x86_64__ +#endif // __BMI__ + +/// \brief Provide the minimum value for a type +/// \tparam T type of class +/// \return the minimum value of the type or class +/// \details NumericLimitsMin() was introduced for Clang at Issue 364, +/// Apple Clang 6.0 and numeric_limits::max() returns 0. +/// \details NumericLimitsMin() requires a specialization for T, +/// meaning std::numeric_limits::is_specialized must return +/// true. In the case of word128 Clang did not specialize +/// numeric_limits for the type. +/// \since Crypto++ 8.1 +template +inline T NumericLimitsMin() +{ + CRYPTOPP_ASSERT(std::numeric_limits::is_specialized); + return (std::numeric_limits::min)(); +} + +/// \brief Provide the maximum value for a type +/// \tparam T type of class +/// \return the maximum value of the type or class +/// \details NumericLimitsMax() was introduced for Clang at Issue 364, +/// Apple Clang 6.0 and numeric_limits::max() returns 0. +/// \details NumericLimitsMax() requires a specialization for T, +/// meaning std::numeric_limits::is_specialized must return +/// true. In the case of word128 Clang did not specialize +/// numeric_limits for the type. +/// \since Crypto++ 8.1 +template +inline T NumericLimitsMax() +{ + CRYPTOPP_ASSERT(std::numeric_limits::is_specialized); + return (std::numeric_limits::max)(); +} + +// NumericLimitsMin and NumericLimitsMax added for word128 types, +// see http://github.com/weidai11/cryptopp/issues/364 +#if defined(CRYPTOPP_WORD128_AVAILABLE) +template<> +inline word128 NumericLimitsMin() +{ + return 0; +} +template<> +inline word128 NumericLimitsMax() +{ +#if defined(CRYPTOPP_APPLE_CLANG_VERSION) + return (static_cast(LWORD_MAX) << 64U) | LWORD_MAX; +#else + return (std::numeric_limits::max)(); +#endif +} +#endif + +/// \brief Performs a saturating subtract clamped at 0 +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param a the minuend +/// \param b the subtrahend +/// \return the difference produced by the saturating subtract +/// \details Saturating arithmetic restricts results to a fixed range. Results that are +/// less than 0 are clamped at 0. +/// \details Use of saturating arithmetic in places can be advantageous because it can +/// avoid a branch by using an instruction like a conditional move (CMOVE). +template +inline T1 SaturatingSubtract(const T1 &a, const T2 &b) +{ + // Generated ASM of a typical clamp, http://gcc.gnu.org/ml/gcc-help/2014-10/msg00112.html + return T1((a > b) ? (a - b) : 0); +} + +/// \brief Performs a saturating subtract clamped at 1 +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param a the minuend +/// \param b the subtrahend +/// \return the difference produced by the saturating subtract +/// \details Saturating arithmetic restricts results to a fixed range. Results that are +/// less than 1 are clamped at 1. +/// \details Use of saturating arithmetic in places can be advantageous because it can +/// avoid a branch by using an instruction like a conditional move (CMOVE). +template +inline T1 SaturatingSubtract1(const T1 &a, const T2 &b) +{ + // Generated ASM of a typical clamp, http://gcc.gnu.org/ml/gcc-help/2014-10/msg00112.html + return T1((a > b) ? (a - b) : 1); +} + +/// \brief Reduces a value to a power of 2 +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param a the first value +/// \param b the second value +/// \return ModPowerOf2() returns a & (b-1). b must be a power of 2. +/// Use IsPowerOf2() to determine if b is a suitable candidate. +/// \sa IsPowerOf2 +template +inline T2 ModPowerOf2(const T1 &a, const T2 &b) +{ + CRYPTOPP_ASSERT(IsPowerOf2(b)); + // Coverity finding CID 170383 Overflowed return value (INTEGER_OVERFLOW) + // Visual Studio and /RTCc warning, https://docs.microsoft.com/en-us/cpp/build/reference/rtc-run-time-error-checks + return T2(a & SaturatingSubtract(b,1U)); +} + +/// \brief Rounds a value down to a multiple of a second value +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param n the value to reduce +/// \param m the value to reduce n to a multiple +/// \return the possibly unmodified value \n +/// \details RoundDownToMultipleOf is effectively a floor function based on m. The function returns +/// the value n - n\%m. If n is a multiple of m, then the original value is returned. +/// \note T1 and T2 should be unsigned arithmetic types. If T1 or +/// T2 is signed, then the value should be non-negative. The library asserts in +/// debug builds when practical, but allows you to perform the operation in release builds. +template +inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m) +{ + // http://github.com/weidai11/cryptopp/issues/364 +#if !defined(CRYPTOPP_APPLE_CLANG_VERSION) || (CRYPTOPP_APPLE_CLANG_VERSION >= 80000) + CRYPTOPP_ASSERT(std::numeric_limits::is_integer); + CRYPTOPP_ASSERT(std::numeric_limits::is_integer); +#endif + + CRYPTOPP_ASSERT(!std::numeric_limits::is_signed || n > 0); + CRYPTOPP_ASSERT(!std::numeric_limits::is_signed || m > 0); + + if (IsPowerOf2(m)) + return n - ModPowerOf2(n, m); + else + return n - n%m; +} + +/// \brief Rounds a value up to a multiple of a second value +/// \tparam T1 class or type +/// \tparam T2 class or type +/// \param n the value to reduce +/// \param m the value to reduce n to a multiple +/// \return the possibly unmodified value \n +/// \details RoundUpToMultipleOf is effectively a ceiling function based on m. The function +/// returns the value n + n\%m. If n is a multiple of m, then the original value is +/// returned. If the value n would overflow, then an InvalidArgument exception is thrown. +/// \note T1 and T2 should be unsigned arithmetic types. If T1 or +/// T2 is signed, then the value should be non-negative. The library asserts in +/// debug builds when practical, but allows you to perform the operation in release builds. +template +inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m) +{ + // http://github.com/weidai11/cryptopp/issues/364 +#if !defined(CRYPTOPP_APPLE_CLANG_VERSION) || (CRYPTOPP_APPLE_CLANG_VERSION >= 80000) + CRYPTOPP_ASSERT(std::numeric_limits::is_integer); + CRYPTOPP_ASSERT(std::numeric_limits::is_integer); +#endif + + CRYPTOPP_ASSERT(!std::numeric_limits::is_signed || n > 0); + CRYPTOPP_ASSERT(!std::numeric_limits::is_signed || m > 0); + + if (NumericLimitsMax() - m + 1 < n) + throw InvalidArgument("RoundUpToMultipleOf: integer overflow"); + return RoundDownToMultipleOf(T1(n+m-1), m); +} + +/// \brief Returns the minimum alignment requirements of a type +/// \tparam T class or type +/// \return the minimum alignment requirements of T, in bytes +/// \details Internally the function calls C++11's alignof if +/// available. If not available, then the function uses compiler +/// specific extensions such as __alignof and _alignof_. +/// If an extension is not available, then the function uses +/// sizeof(T). +template +inline unsigned int GetAlignmentOf() +{ +#if defined(CRYPTOPP_CXX11_ALIGNOF) + return alignof(T); +#elif (CRYPTOPP_MSC_VERSION >= 1300) + return __alignof(T); +#elif defined(__GNUC__) + return __alignof__(T); +#elif defined(__SUNPRO_CC) + return __alignof__(T); +#elif defined(__IBM_ALIGNOF__) + return __alignof__(T); +#elif CRYPTOPP_BOOL_SLOW_WORD64 + return UnsignedMin(4U, sizeof(T)); +#else + return sizeof(T); +#endif +} + +/// \brief Determines whether ptr is aligned to a minimum value +/// \param ptr the pointer being checked for alignment +/// \param alignment the alignment value to test the pointer against +/// \return true if ptr is aligned on at least alignment +/// boundary, false otherwise +/// \details Internally the function tests whether alignment is 1. If so, +/// the function returns true. If not, then the function effectively +/// performs a modular reduction and returns true if the residue is 0. +inline bool IsAlignedOn(const void *ptr, unsigned int alignment) +{ + const uintptr_t x = reinterpret_cast(ptr); + return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2(x, alignment) == 0 : x % alignment == 0); +} + +/// \brief Determines whether ptr is minimally aligned +/// \tparam T class or type +/// \param ptr the pointer to check for alignment +/// \return true if ptr is aligned to at least T +/// boundary, false otherwise +/// \details Internally the function calls IsAlignedOn with a second +/// parameter of GetAlignmentOf. +template +inline bool IsAligned(const void *ptr) +{ + return IsAlignedOn(ptr, GetAlignmentOf()); +} + +#if (CRYPTOPP_LITTLE_ENDIAN) +typedef LittleEndian NativeByteOrder; +#elif (CRYPTOPP_BIG_ENDIAN) +typedef BigEndian NativeByteOrder; +#else +# error "Unable to determine endianness" +#endif + +/// \brief Returns NativeByteOrder as an enumerated ByteOrder value +/// \return LittleEndian if the native byte order is little-endian, +/// and BigEndian if the native byte order is big-endian +/// \details NativeByteOrder is a typedef depending on the platform. +/// If CRYPTOPP_LITTLE_ENDIAN is set in config.h, then +/// GetNativeByteOrder returns LittleEndian. If CRYPTOPP_BIG_ENDIAN +/// is set, then GetNativeByteOrder returns BigEndian. +/// \note There are other byte orders besides little- and big-endian, +/// and they include bi-endian and PDP-endian. If a system is neither +/// little-endian nor big-endian, then a compile time error occurs. +inline ByteOrder GetNativeByteOrder() +{ + return NativeByteOrder::ToEnum(); +} + +/// \brief Determines whether order follows native byte ordering +/// \param order the ordering being tested against native byte ordering +/// \return true if order follows native byte ordering, false otherwise +inline bool NativeByteOrderIs(ByteOrder order) +{ + return order == GetNativeByteOrder(); +} + +/// \brief Returns the direction the cipher is being operated +/// \tparam T class or type +/// \param obj the cipher object being queried +/// \return ENCRYPTION if the cipher obj is being operated in its forward direction, +/// DECRYPTION otherwise +/// \details A cipher can be operated in a "forward" direction (encryption) or a "reverse" +/// direction (decryption). The operations do not have to be symmetric, meaning a second +/// application of the transformation does not necessarily return the original message. +/// That is, E(D(m)) may not equal E(E(m)); and D(E(m)) may not +/// equal D(D(m)). +template +inline CipherDir GetCipherDir(const T &obj) +{ + return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; +} + +/// \brief Performs an addition with carry on a block of bytes +/// \param inout the byte block +/// \param size the size of the block, in bytes +/// \details Performs an addition with carry by adding 1 on a block of bytes starting at the least +/// significant byte. Once carry is 0, the function terminates and returns to the caller. +/// \note The function is not constant time because it stops processing when the carry is 0. +inline void IncrementCounterByOne(byte *inout, unsigned int size) +{ + CRYPTOPP_ASSERT(inout != NULLPTR); + + unsigned int carry=1; + while (carry && size != 0) + { + // On carry inout[n] equals 0 + carry = ! ++inout[size-1]; + size--; + } +} + +/// \brief Performs an addition with carry on a block of bytes +/// \param output the destination block of bytes +/// \param input the source block of bytes +/// \param size the size of the block +/// \details Performs an addition with carry on a block of bytes starting at the least significant +/// byte. Once carry is 0, the remaining bytes from input are copied to output using memcpy. +/// \details The function is close to near-constant time because it operates on all the bytes in the blocks. +inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int size) +{ + CRYPTOPP_ASSERT(output != NULLPTR); + CRYPTOPP_ASSERT(input != NULLPTR); + + unsigned int carry=1; + while (carry && size != 0) + { + // On carry output[n] equals 0 + carry = ! (output[size-1] = input[size-1] + 1); + size--; + } + + while (size != 0) + { + output[size-1] = input[size-1]; + size--; + } +} + +/// \brief Performs a branch-less swap of values a and b if condition c is true +/// \tparam T class or type +/// \param c the condition to perform the swap +/// \param a the first value +/// \param b the second value +template +inline void ConditionalSwap(bool c, T &a, T &b) +{ + T t = c * (a ^ b); + a ^= t; + b ^= t; +} + +/// \brief Performs a branch-less swap of pointers a and b if condition c is true +/// \tparam T class or type +/// \param c the condition to perform the swap +/// \param a the first pointer +/// \param b the second pointer +template +inline void ConditionalSwapPointers(bool c, T &a, T &b) +{ + ptrdiff_t t = size_t(c) * (a - b); + a -= t; + b += t; +} + +// see http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/protect-secrets.html +// and http://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data + +/// \brief Sets each element of an array to 0 +/// \tparam T class or type +/// \param buf an array of elements +/// \param n the number of elements in the array +/// \details The operation performs a wipe or zeroization. The function +/// attempts to survive optimizations and dead code removal. +template +void SecureWipeBuffer(T *buf, size_t n) +{ + // GCC 4.3.2 on Cygwin optimizes away the first store if this + // loop is done in the forward direction + volatile T *p = buf+n; + while (n--) + *(--p) = 0; +} + +#if !defined(CRYPTOPP_DISABLE_ASM) && \ + (CRYPTOPP_MSC_VERSION >= 1400 || defined(__GNUC__)) && \ + (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) + +/// \brief Sets each byte of an array to 0 +/// \param buf an array of bytes +/// \param n the number of elements in the array +/// \details The operation performs a wipe or zeroization. The function +/// attempts to survive optimizations and dead code removal. +template<> inline void SecureWipeBuffer(byte *buf, size_t n) +{ + volatile byte *p = buf; +#ifdef __GNUC__ + asm volatile("rep stosb" : "+c"(n), "+D"(p) : "a"(0) : "memory"); +#else + __stosb(reinterpret_cast(reinterpret_cast(p)), 0, n); +#endif +} + +/// \brief Sets each 16-bit element of an array to 0 +/// \param buf an array of 16-bit words +/// \param n the number of elements in the array +/// \details The operation performs a wipe or zeroization. The function +/// attempts to survive optimizations and dead code removal. +template<> inline void SecureWipeBuffer(word16 *buf, size_t n) +{ + volatile word16 *p = buf; +#ifdef __GNUC__ + asm volatile("rep stosw" : "+c"(n), "+D"(p) : "a"(0) : "memory"); +#else + __stosw(reinterpret_cast(reinterpret_cast(p)), 0, n); +#endif +} + +/// \brief Sets each 32-bit element of an array to 0 +/// \param buf an array of 32-bit words +/// \param n the number of elements in the array +/// \details The operation performs a wipe or zeroization. The function +/// attempts to survive optimizations and dead code removal. +template<> inline void SecureWipeBuffer(word32 *buf, size_t n) +{ + volatile word32 *p = buf; +#ifdef __GNUC__ + asm volatile("rep stosl" : "+c"(n), "+D"(p) : "a"(0) : "memory"); +#else + __stosd(reinterpret_cast(reinterpret_cast(p)), 0, n); +#endif +} + +/// \brief Sets each 64-bit element of an array to 0 +/// \param buf an array of 64-bit words +/// \param n the number of elements in the array +/// \details The operation performs a wipe or zeroization. The function +/// attempts to survive optimizations and dead code removal. +template<> inline void SecureWipeBuffer(word64 *buf, size_t n) +{ +#if CRYPTOPP_BOOL_X64 + volatile word64 *p = buf; +# ifdef __GNUC__ + asm volatile("rep stosq" : "+c"(n), "+D"(p) : "a"(0) : "memory"); +# else + __stosq(const_cast(p), 0, n); +# endif +#else + SecureWipeBuffer(reinterpret_cast(buf), 2*n); +#endif +} + +#endif // CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 + +#if !defined(CRYPTOPP_DISABLE_ASM) && (CRYPTOPP_MSC_VERSION >= 1700) && defined(_M_ARM) +template<> inline void SecureWipeBuffer(byte *buf, size_t n) +{ + char *p = reinterpret_cast(buf+n); + while (n--) + __iso_volatile_store8(--p, 0); +} + +template<> inline void SecureWipeBuffer(word16 *buf, size_t n) +{ + short *p = reinterpret_cast(buf+n); + while (n--) + __iso_volatile_store16(--p, 0); +} + +template<> inline void SecureWipeBuffer(word32 *buf, size_t n) +{ + int *p = reinterpret_cast(buf+n); + while (n--) + __iso_volatile_store32(--p, 0); +} + +template<> inline void SecureWipeBuffer(word64 *buf, size_t n) +{ + __int64 *p = reinterpret_cast<__int64*>(buf+n); + while (n--) + __iso_volatile_store64(--p, 0); +} +#endif + +/// \brief Sets each element of an array to 0 +/// \tparam T class or type +/// \param buf an array of elements +/// \param n the number of elements in the array +/// \details The operation performs a wipe or zeroization. The function +/// attempts to survive optimizations and dead code removal. +template +inline void SecureWipeArray(T *buf, size_t n) +{ + if (sizeof(T) % 8 == 0 && GetAlignmentOf() % GetAlignmentOf() == 0) + SecureWipeBuffer(reinterpret_cast(static_cast(buf)), n * (sizeof(T)/8)); + else if (sizeof(T) % 4 == 0 && GetAlignmentOf() % GetAlignmentOf() == 0) + SecureWipeBuffer(reinterpret_cast(static_cast(buf)), n * (sizeof(T)/4)); + else if (sizeof(T) % 2 == 0 && GetAlignmentOf() % GetAlignmentOf() == 0) + SecureWipeBuffer(reinterpret_cast(static_cast(buf)), n * (sizeof(T)/2)); + else + SecureWipeBuffer(reinterpret_cast(static_cast(buf)), n * sizeof(T)); +} + +/// \brief Converts a wide character C-string to a multibyte string +/// \param str C-string consisting of wide characters +/// \param throwOnError flag indicating the function should throw on error +/// \return str converted to a multibyte string or an empty string. +/// \details StringNarrow() converts a wide string to a narrow string using C++ std::wcstombs() under +/// the executing thread's locale. A locale must be set before using this function, and it can be +/// set with std::setlocale() if needed. Upon success, the converted string is returned. +/// \details Upon failure with throwOnError as false, the function returns an empty string. If +/// throwOnError as true, the function throws an InvalidArgument() exception. +/// \note If you try to convert, say, the Chinese character for "bone" from UTF-16 (0x9AA8) to UTF-8 +/// (0xE9 0xAA 0xA8), then you must ensure the locale is available. If the locale is not available, +/// then a 0x21 error is returned on Windows which eventually results in an InvalidArgument() exception. +std::string StringNarrow(const wchar_t *str, bool throwOnError = true); + +/// \brief Converts a multibyte C-string to a wide character string +/// \param str C-string consisting of wide characters +/// \param throwOnError flag indicating the function should throw on error +/// \return str converted to a multibyte string or an empty string. +/// \details StringWiden() converts a narrow string to a wide string using C++ std::mbstowcs() under +/// the executing thread's locale. A locale must be set before using this function, and it can be +/// set with std::setlocale() if needed. Upon success, the converted string is returned. +/// \details Upon failure with throwOnError as false, the function returns an empty string. If +/// throwOnError as true, the function throws an InvalidArgument() exception. +/// \note If you try to convert, say, the Chinese character for "bone" from UTF-8 (0xE9 0xAA 0xA8) +/// to UTF-16 (0x9AA8), then you must ensure the locale is available. If the locale is not available, +/// then a 0x21 error is returned on Windows which eventually results in an InvalidArgument() exception. +std::wstring StringWiden(const char *str, bool throwOnError = true); + +// ************** rotate functions *************** + +/// \brief Performs a left rotate +/// \tparam R the number of bit positions to rotate the value +/// \tparam T the word type +/// \param x the value to rotate +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details R must be in the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// Use rotlMod if the rotate amount R is outside the range. +/// \details Use rotlConstant when the rotate amount is constant. The template function was added +/// because Clang did not propagate the constant when passed as a function parameter. Clang's +/// need for a constexpr meant rotlFixed failed to compile on occasion. +/// \note rotlConstant attempts to enlist a rotate IMM instruction because its often faster +/// than a rotate REG. Immediate rotates can be up to three times faster than their register +/// counterparts. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 6.0 +template inline T rotlConstant(T x) +{ + // Portable rotate that reduces to single instruction... + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157, + // http://software.intel.com/en-us/forums/topic/580884 + // and http://llvm.org/bugs/show_bug.cgi?id=24226 + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + CRYPTOPP_ASSERT(static_cast(R) < THIS_SIZE); + return T((x<>(-R&MASK))); +} + +/// \brief Performs a right rotate +/// \tparam R the number of bit positions to rotate the value +/// \tparam T the word type +/// \param x the value to rotate +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details R must be in the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// Use rotrMod if the rotate amount R is outside the range. +/// \details Use rotrConstant when the rotate amount is constant. The template function was added +/// because Clang did not propagate the constant when passed as a function parameter. Clang's +/// need for a constexpr meant rotrFixed failed to compile on occasion. +/// \note rotrConstant attempts to enlist a rotate IMM instruction because its often faster +/// than a rotate REG. Immediate rotates can be up to three times faster than their register +/// counterparts. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +template inline T rotrConstant(T x) +{ + // Portable rotate that reduces to single instruction... + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157, + // http://software.intel.com/en-us/forums/topic/580884 + // and http://llvm.org/bugs/show_bug.cgi?id=24226 + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + CRYPTOPP_ASSERT(static_cast(R) < THIS_SIZE); + return T((x >> R)|(x<<(-R&MASK))); +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details y must be in the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// Use rotlMod if the rotate amount y is outside the range. +/// \note rotlFixed attempts to enlist a rotate IMM instruction because its often faster +/// than a rotate REG. Immediate rotates can be up to three times faster than their register +/// counterparts. New code should use rotlConstant, which accepts the rotate amount as a +/// template parameter. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 6.0 +template inline T rotlFixed(T x, unsigned int y) +{ + // Portable rotate that reduces to single instruction... + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157, + // http://software.intel.com/en-us/forums/topic/580884 + // and http://llvm.org/bugs/show_bug.cgi?id=24226 + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + CRYPTOPP_ASSERT(static_cast(y) < THIS_SIZE); + return T((x<>(-y&MASK))); +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details y must be in the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// Use rotrMod if the rotate amount y is outside the range. +/// \note rotrFixed attempts to enlist a rotate IMM instruction because its often faster +/// than a rotate REG. Immediate rotates can be up to three times faster than their register +/// counterparts. New code should use rotrConstant, which accepts the rotate amount as a +/// template parameter. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 3.0 +template inline T rotrFixed(T x, unsigned int y) +{ + // Portable rotate that reduces to single instruction... + // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157, + // http://software.intel.com/en-us/forums/topic/580884 + // and http://llvm.org/bugs/show_bug.cgi?id=24226 + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + CRYPTOPP_ASSERT(static_cast(y) < THIS_SIZE); + return T((x >> y)|(x<<(-y&MASK))); +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details y must be in the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// Use rotlMod if the rotate amount y is outside the range. +/// \note rotlVariable attempts to enlist a rotate IMM instruction because its often faster +/// than a rotate REG. Immediate rotates can be up to three times faster than their register +/// counterparts. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 3.0 +template inline T rotlVariable(T x, unsigned int y) +{ + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + CRYPTOPP_ASSERT(static_cast(y) < THIS_SIZE); + return T((x<>(-y&MASK))); +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details y must be in the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// Use rotrMod if the rotate amount y is outside the range. +/// \note rotrVariable attempts to enlist a rotate IMM instruction because its often faster +/// than a rotate REG. Immediate rotates can be up to three times faster than their register +/// counterparts. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 3.0 +template inline T rotrVariable(T x, unsigned int y) +{ + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + CRYPTOPP_ASSERT(static_cast(y) < THIS_SIZE); + return T((x>>y)|(x<<(-y&MASK))); +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details y is reduced to the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrVariable will use either rotate IMM or rotate REG. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 3.0 +template inline T rotlMod(T x, unsigned int y) +{ + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + return T((x<<(y&MASK))|(x>>(-y&MASK))); +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide. +/// \details y is reduced to the range [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrVariable will use either rotate IMM or rotate REG. +/// \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable +/// \since Crypto++ 3.0 +template inline T rotrMod(T x, unsigned int y) +{ + CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8); + CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1); + return T((x>>(y&MASK))|(x<<(-y&MASK))); +} + +#ifdef CRYPTOPP_MSC_VERSION + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the 32-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotl provided by +/// . The value x to be rotated is 32-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotlFixed will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word32 rotlFixed(word32 x, unsigned int y) +{ + // Uses Microsoft call, bound to C/C++ language rules. + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _lrotl(x, static_cast(y)) : x; +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the 32-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotr provided by +/// . The value x to be rotated is 32-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrFixed will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word32 rotrFixed(word32 x, unsigned int y) +{ + // Uses Microsoft call, bound to C/C++ language rules. + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _lrotr(x, static_cast(y)) : x; +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the 32-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotl provided by +/// . The value x to be rotated is 32-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotlVariable will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word32 rotlVariable(word32 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return _lrotl(x, static_cast(y)); +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the 32-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotr provided by +/// . The value x to be rotated is 32-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrVariable will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word32 rotrVariable(word32 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return _lrotr(x, static_cast(y)); +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the 32-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotl provided by +/// . The value x to be rotated is 32-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \since Crypto++ 3.0 +template<> inline word32 rotlMod(word32 x, unsigned int y) +{ + y %= 8*sizeof(x); + return _lrotl(x, static_cast(y)); +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the 32-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotr provided by +/// . The value x to be rotated is 32-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \since Crypto++ 3.0 +template<> inline word32 rotrMod(word32 x, unsigned int y) +{ + y %= 8*sizeof(x); + return _lrotr(x, static_cast(y)); +} + +#endif // #ifdef CRYPTOPP_MSC_VERSION + +#if (CRYPTOPP_MSC_VERSION >= 1400) || (defined(CRYPTOPP_MSC_VERSION) && !defined(_DLL)) +// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the 64-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotl provided by +/// . The value x to be rotated is 64-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrFixed will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word64 rotlFixed(word64 x, unsigned int y) +{ + // Uses Microsoft call, bound to C/C++ language rules. + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _rotl64(x, static_cast(y)) : x; +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the 64-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotr provided by +/// . The value x to be rotated is 64-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrFixed will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word64 rotrFixed(word64 x, unsigned int y) +{ + // Uses Microsoft call, bound to C/C++ language rules. + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _rotr64(x, static_cast(y)) : x; +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the 64-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotl provided by +/// . The value x to be rotated is 64-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotlVariable will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word64 rotlVariable(word64 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return _rotl64(x, static_cast(y)); +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the 64-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotr provided by +/// . The value x to be rotated is 64-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \note rotrVariable will assert in Debug builds if is outside the allowed range. +/// \since Crypto++ 3.0 +template<> inline word64 rotrVariable(word64 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _rotr64(x, static_cast(y)) : x; +} + +/// \brief Performs a left rotate +/// \tparam T the word type +/// \param x the 64-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotl provided by +/// . The value x to be rotated is 64-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \since Crypto++ 3.0 +template<> inline word64 rotlMod(word64 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _rotl64(x, static_cast(y)) : x; +} + +/// \brief Performs a right rotate +/// \tparam T the word type +/// \param x the 64-bit value to rotate +/// \param y the number of bit positions to rotate the value +/// \details This is a Microsoft specific implementation using _lrotr provided by +/// . The value x to be rotated is 64-bits. y must be in the range +/// [0, sizeof(T)*8 - 1] to avoid undefined behavior. +/// \since Crypto++ 3.0 +template<> inline word64 rotrMod(word64 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 8*sizeof(x)); + return y ? _rotr64(x, static_cast(y)) : x; +} + +#endif // #if CRYPTOPP_MSC_VERSION >= 1310 + +#if CRYPTOPP_MSC_VERSION >= 1400 && !defined(__INTEL_COMPILER) +// Intel C++ Compiler 10.0 gives undefined externals with these +template<> inline word16 rotlFixed(word16 x, unsigned int y) +{ + // Intrinsic, not bound to C/C++ language rules. + return _rotl16(x, static_cast(y)); +} + +template<> inline word16 rotrFixed(word16 x, unsigned int y) +{ + // Intrinsic, not bound to C/C++ language rules. + return _rotr16(x, static_cast(y)); +} + +template<> inline word16 rotlVariable(word16 x, unsigned int y) +{ + return _rotl16(x, static_cast(y)); +} + +template<> inline word16 rotrVariable(word16 x, unsigned int y) +{ + return _rotr16(x, static_cast(y)); +} + +template<> inline word16 rotlMod(word16 x, unsigned int y) +{ + return _rotl16(x, static_cast(y)); +} + +template<> inline word16 rotrMod(word16 x, unsigned int y) +{ + return _rotr16(x, static_cast(y)); +} + +template<> inline byte rotlFixed(byte x, unsigned int y) +{ + // Intrinsic, not bound to C/C++ language rules. + return _rotl8(x, static_cast(y)); +} + +template<> inline byte rotrFixed(byte x, unsigned int y) +{ + // Intrinsic, not bound to C/C++ language rules. + return _rotr8(x, static_cast(y)); +} + +template<> inline byte rotlVariable(byte x, unsigned int y) +{ + return _rotl8(x, static_cast(y)); +} + +template<> inline byte rotrVariable(byte x, unsigned int y) +{ + return _rotr8(x, static_cast(y)); +} + +template<> inline byte rotlMod(byte x, unsigned int y) +{ + return _rotl8(x, static_cast(y)); +} + +template<> inline byte rotrMod(byte x, unsigned int y) +{ + return _rotr8(x, static_cast(y)); +} + +#endif // #if CRYPTOPP_MSC_VERSION >= 1400 + +#if (defined(__MWERKS__) && TARGET_CPU_PPC) + +template<> inline word32 rotlFixed(word32 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 32); + return y ? __rlwinm(x,y,0,31) : x; +} + +template<> inline word32 rotrFixed(word32 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 32); + return y ? __rlwinm(x,32-y,0,31) : x; +} + +template<> inline word32 rotlVariable(word32 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 32); + return (__rlwnm(x,y,0,31)); +} + +template<> inline word32 rotrVariable(word32 x, unsigned int y) +{ + CRYPTOPP_ASSERT(y < 32); + return (__rlwnm(x,32-y,0,31)); +} + +template<> inline word32 rotlMod(word32 x, unsigned int y) +{ + return (__rlwnm(x,y,0,31)); +} + +template<> inline word32 rotrMod(word32 x, unsigned int y) +{ + return (__rlwnm(x,32-y,0,31)); +} + +#endif // __MWERKS__ && TARGET_CPU_PPC + +// ************** endian reversal *************** + +/// \brief Gets a byte from a value +/// \param order the ByteOrder of the value +/// \param value the value to retrieve the byte +/// \param index the location of the byte to retrieve +template +inline unsigned int GetByte(ByteOrder order, T value, unsigned int index) +{ + if (order == LITTLE_ENDIAN_ORDER) + return GETBYTE(value, index); + else + return GETBYTE(value, sizeof(T)-index-1); +} + +/// \brief Reverses bytes in a 8-bit value +/// \param value the 8-bit value to reverse +/// \note ByteReverse returns the value passed to it since there is nothing to +/// reverse. +inline byte ByteReverse(byte value) +{ + return value; +} + +/// \brief Reverses bytes in a 16-bit value +/// \param value the 16-bit value to reverse +/// \details ByteReverse calls bswap if available. Otherwise the function +/// performs a 8-bit rotate on the word16. +inline word16 ByteReverse(word16 value) +{ +#if defined(CRYPTOPP_BYTESWAP_AVAILABLE) + return bswap_16(value); +#elif (CRYPTOPP_MSC_VERSION >= 1400) || (defined(CRYPTOPP_MSC_VERSION) && !defined(_DLL)) + return _byteswap_ushort(value); +#else + return rotlFixed(value, 8U); +#endif +} + +/// \brief Reverses bytes in a 32-bit value +/// \param value the 32-bit value to reverse +/// \details ByteReverse calls bswap if available. Otherwise the function uses +/// a combination of rotates on the word32. +inline word32 ByteReverse(word32 value) +{ +#if defined(CRYPTOPP_BYTESWAP_AVAILABLE) + return bswap_32(value); +#elif defined(CRYPTOPP_ARM_BYTEREV_AVAILABLE) + word32 rvalue; + __asm__ ("rev %0, %1" : "=r" (rvalue) : "r" (value)); + return rvalue; +#elif defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) + __asm__ ("bswap %0" : "=r" (value) : "0" (value)); + return value; +#elif defined(__MWERKS__) && TARGET_CPU_PPC + return (word32)__lwbrx(&value,0); +#elif (CRYPTOPP_MSC_VERSION >= 1400) || (defined(CRYPTOPP_MSC_VERSION) && !defined(_DLL)) + return _byteswap_ulong(value); +#elif CRYPTOPP_FAST_ROTATE(32) && !defined(__xlC__) + // 5 instructions with rotate instruction, 9 without + return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); +#else + // 6 instructions with rotate instruction, 8 without + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return rotlFixed(value, 16U); +#endif +} + +/// \brief Reverses bytes in a 64-bit value +/// \param value the 64-bit value to reverse +/// \details ByteReverse calls bswap if available. Otherwise the function uses +/// a combination of rotates on the word64. +inline word64 ByteReverse(word64 value) +{ +#if defined(CRYPTOPP_BYTESWAP_AVAILABLE) + return bswap_64(value); +#elif defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__) + __asm__ ("bswap %0" : "=r" (value) : "0" (value)); + return value; +#elif (CRYPTOPP_MSC_VERSION >= 1400) || (defined(CRYPTOPP_MSC_VERSION) && !defined(_DLL)) + return _byteswap_uint64(value); +#elif CRYPTOPP_BOOL_SLOW_WORD64 + return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32)); +#else + value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); + value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); + return rotlFixed(value, 32U); +#endif +} + +#if defined(CRYPTOPP_WORD128_AVAILABLE) +/// \brief Reverses bytes in a 128-bit value +/// \param value the 128-bit value to reverse +/// \details ByteReverse calls bswap if available. Otherwise the function uses +/// a combination of rotates on the word128. +/// \note word128 is available on some 64-bit platforms when the compiler supports it. +/// \since Crypto++ 8.7 +inline word128 ByteReverse(word128 value) +{ + // TODO: speed this up + return (word128(ByteReverse(word64(value))) << 64) | ByteReverse(word64(value>>64)); +} +#endif + +/// \brief Reverses bits in a 8-bit value +/// \param value the 8-bit value to reverse +/// \details BitReverse performs a combination of shifts on the byte. +inline byte BitReverse(byte value) +{ + value = byte((value & 0xAA) >> 1) | byte((value & 0x55) << 1); + value = byte((value & 0xCC) >> 2) | byte((value & 0x33) << 2); + return rotlFixed(value, 4U); +} + +/// \brief Reverses bits in a 16-bit value +/// \param value the 16-bit value to reverse +/// \details BitReverse performs a combination of shifts on the word16. +inline word16 BitReverse(word16 value) +{ +#if defined(CRYPTOPP_ARM_BITREV_AVAILABLE) + // 4 instructions on ARM. + word32 rvalue; + __asm__ ("rbit %0, %1" : "=r" (rvalue) : "r" (value)); + return word16(rvalue >> 16); +#else + // 15 instructions on ARM. + value = word16((value & 0xAAAA) >> 1) | word16((value & 0x5555) << 1); + value = word16((value & 0xCCCC) >> 2) | word16((value & 0x3333) << 2); + value = word16((value & 0xF0F0) >> 4) | word16((value & 0x0F0F) << 4); + return ByteReverse(value); +#endif +} + +/// \brief Reverses bits in a 32-bit value +/// \param value the 32-bit value to reverse +/// \details BitReverse performs a combination of shifts on the word32. +inline word32 BitReverse(word32 value) +{ +#if defined(CRYPTOPP_ARM_BITREV_AVAILABLE) + // 2 instructions on ARM. + word32 rvalue; + __asm__ ("rbit %0, %1" : "=r" (rvalue) : "r" (value)); + return rvalue; +#else + // 19 instructions on ARM. + value = word32((value & 0xAAAAAAAA) >> 1) | word32((value & 0x55555555) << 1); + value = word32((value & 0xCCCCCCCC) >> 2) | word32((value & 0x33333333) << 2); + value = word32((value & 0xF0F0F0F0) >> 4) | word32((value & 0x0F0F0F0F) << 4); + return ByteReverse(value); +#endif +} + +/// \brief Reverses bits in a 64-bit value +/// \param value the 64-bit value to reverse +/// \details BitReverse performs a combination of shifts on the word64. +inline word64 BitReverse(word64 value) +{ +#if CRYPTOPP_BOOL_SLOW_WORD64 + return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32)); +#else + value = word64((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | word64((value & W64LIT(0x5555555555555555)) << 1); + value = word64((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | word64((value & W64LIT(0x3333333333333333)) << 2); + value = word64((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | word64((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4); + return ByteReverse(value); +#endif +} + +/// \brief Reverses bits in a value +/// \param value the value to reverse +/// \details The template overload of BitReverse operates on signed and unsigned values. +/// Internally the size of T is checked, and then value is cast to a byte, +/// word16, word32 or word64. After the cast, the appropriate BitReverse +/// overload is called. +/// \note word128 is available on some 64-bit platforms when the compiler supports it. +/// \since Crypto++ 1.0, word128 since Crypto++ 8.7 +template +inline T BitReverse(T value) +{ + if (sizeof(T) == 1) + return (T)BitReverse((byte)value); + else if (sizeof(T) == 2) + return (T)BitReverse((word16)value); + else if (sizeof(T) == 4) + return (T)BitReverse((word32)value); + else if (sizeof(T) == 8) + return (T)BitReverse((word64)value); +#if defined(CRYPTOPP_WORD128_AVAILABLE) + else if (sizeof(T) == 16) + return (T)BitReverse((word128)value); +#endif + else + { + CRYPTOPP_ASSERT(0); + return (T)BitReverse((word64)value); + } +} + +/// \brief Reverses bytes in a value depending upon endianness +/// \tparam T the class or type +/// \param order the ByteOrder of the data +/// \param value the value to conditionally reverse +/// \details Internally, the ConditionalByteReverse calls NativeByteOrderIs. +/// If order matches native byte order, then the original value is returned. +/// If not, then ByteReverse is called on the value before returning to the caller. +template +inline T ConditionalByteReverse(ByteOrder order, T value) +{ + return NativeByteOrderIs(order) ? value : ByteReverse(value); +} + +/// \brief Reverses bytes in an element from an array of elements +/// \tparam T the class or type +/// \param out the output array of elements +/// \param in the input array of elements +/// \param byteCount the total number of bytes in the array +/// \details Internally, ByteReverse visits each element in the in array +/// calls ByteReverse on it, and writes the result to out. +/// \details ByteReverse does not process tail byes, or bytes that are +/// not part of a full element. If T is int (and int is 4 bytes), then +/// byteCount = 10 means only the first 2 elements or 8 bytes are +/// reversed. +/// \details The following program should help illustrate the behavior. +///
vector v1, v2;
+///
+/// v1.push_back(1);
+/// v1.push_back(2);
+/// v1.push_back(3);
+/// v1.push_back(4);
+///
+/// v2.resize(v1.size());
+/// ByteReverse(&v2[0], &v1[0], 16);
+///
+/// cout << "V1: ";
+/// for(unsigned int i = 0; i < v1.size(); i++)
+///   cout << std::hex << v1[i] << " ";
+/// cout << endl;
+///
+/// cout << "V2: ";
+/// for(unsigned int i = 0; i < v2.size(); i++)
+///   cout << std::hex << v2[i] << " ";
+/// cout << endl;
+/// The program above results in the following output. +///
V1: 00000001 00000002 00000003 00000004
+/// V2: 01000000 02000000 03000000 04000000
+/// \sa ConditionalByteReverse +template +void ByteReverse(T *out, const T *in, size_t byteCount) +{ + // Alignment check due to Issues 690 + CRYPTOPP_ASSERT(byteCount % sizeof(T) == 0); + CRYPTOPP_ASSERT(IsAligned(in)); + CRYPTOPP_ASSERT(IsAligned(out)); + + size_t count = byteCount/sizeof(T); + for (size_t i=0; ibyteCount = 10 means only the first 2 elements or 8 bytes are +/// reversed. +/// \sa ByteReverse +template +inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount) +{ + if (!NativeByteOrderIs(order)) + ByteReverse(out, in, byteCount); + else if (in != out) + memcpy_s(out, byteCount, in, byteCount); +} + +/// \brief Copy bytes in a buffer to an array of elements in big-endian order +/// \tparam T the class or type +/// \param order the ByteOrder of the data +/// \param out the output array of elements +/// \param outlen the byte count of the array +/// \param in the input array of elements +/// \param inlen the byte count of the array +template +inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen) +{ + const size_t U = sizeof(T); + CRYPTOPP_ASSERT(inlen <= outlen*U); + memcpy_s(out, outlen*U, in, inlen); + memset_z((byte *)out+inlen, 0, outlen*U-inlen); + ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U)); +} + +/// \brief Retrieve a byte from an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned buffer +/// \param unused dummy parameter +/// \return byte value +/// \details UnalignedGetWordNonTemplate accesses an unaligned buffer and returns a byte value. +/// \since Crypto++ 1.0 +inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *unused) +{ + CRYPTOPP_UNUSED(order); CRYPTOPP_UNUSED(unused); + return block[0]; +} + +/// \brief Retrieve a word16 from an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned buffer +/// \param unused dummy parameter +/// \return byte value +/// \details UnalignedGetWordNonTemplate accesses an unaligned buffer and returns a word16 value. +/// \since Crypto++ 1.0 +inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *unused) +{ + CRYPTOPP_UNUSED(unused); + return (order == BIG_ENDIAN_ORDER) + ? block[1] | (block[0] << 8) + : block[0] | (block[1] << 8); +} + +/// \brief Retrieve a word32 from an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned buffer +/// \param unused dummy parameter +/// \return byte value +/// \details UnalignedGetWordNonTemplate accesses an unaligned buffer and returns a word32 value. +/// \since Crypto++ 1.0 +inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *unused) +{ + CRYPTOPP_UNUSED(unused); + return (order == BIG_ENDIAN_ORDER) + ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24) + : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24); +} + +/// \brief Retrieve a word64 from an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned buffer +/// \param unused dummy parameter +/// \return byte value +/// \details UnalignedGetWordNonTemplate accesses an unaligned buffer and returns a word64 value. +/// \since Crypto++ 1.0 +inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *unused) +{ + CRYPTOPP_UNUSED(unused); + return (order == BIG_ENDIAN_ORDER) + ? + (word64(block[7]) | + (word64(block[6]) << 8) | + (word64(block[5]) << 16) | + (word64(block[4]) << 24) | + (word64(block[3]) << 32) | + (word64(block[2]) << 40) | + (word64(block[1]) << 48) | + (word64(block[0]) << 56)) + : + (word64(block[0]) | + (word64(block[1]) << 8) | + (word64(block[2]) << 16) | + (word64(block[3]) << 24) | + (word64(block[4]) << 32) | + (word64(block[5]) << 40) | + (word64(block[6]) << 48) | + (word64(block[7]) << 56)); +} + +#if defined(CRYPTOPP_WORD128_AVAILABLE) +/// \brief Retrieve a word128 from an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned buffer +/// \param unused dummy parameter +/// \return byte value +/// \details UnalignedGetWordNonTemplate accesses an unaligned buffer and returns a word128 value. +/// \note word128 is available on some 64-bit platforms when the compiler supports it. +/// \since Crypto++ 8.7 +inline word128 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word128 *unused) +{ + CRYPTOPP_UNUSED(unused); + return (order == BIG_ENDIAN_ORDER) + ? + (word128(block[15]) | + (word128(block[14]) << 8) | + (word128(block[13]) << 16) | + (word128(block[12]) << 24) | + (word128(block[11]) << 32) | + (word128(block[10]) << 40) | + (word128(block[ 9]) << 48) | + (word128(block[ 8]) << 56) | + (word128(block[ 7]) << 64) | + (word128(block[ 6]) << 72) | + (word128(block[ 5]) << 80) | + (word128(block[ 4]) << 88) | + (word128(block[ 3]) << 96) | + (word128(block[ 2]) << 104) | + (word128(block[ 1]) << 112) | + (word128(block[ 0]) << 120)) + : + (word128(block[ 0]) | + (word128(block[ 1]) << 8) | + (word128(block[ 2]) << 16) | + (word128(block[ 3]) << 24) | + (word128(block[ 4]) << 32) | + (word128(block[ 5]) << 40) | + (word128(block[ 6]) << 48) | + (word128(block[ 7]) << 56) | + (word128(block[ 8]) << 64) | + (word128(block[ 9]) << 72) | + (word128(block[10]) << 80) | + (word128(block[11]) << 88) | + (word128(block[12]) << 96) | + (word128(block[13]) << 104) | + (word128(block[14]) << 112) | + (word128(block[15]) << 120)); +} +#endif + +/// \brief Write a byte to an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned output buffer +/// \param value byte value +/// \param xorBlock optional unaligned xor buffer +/// \details UnalignedbyteNonTemplate writes a byte value to an unaligned buffer. +/// \since Crypto++ 1.0 +inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock) +{ + CRYPTOPP_UNUSED(order); + block[0] = static_cast(xorBlock ? (value ^ xorBlock[0]) : value); +} + +/// \brief Write a word16 to an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned output buffer +/// \param value word16 value +/// \param xorBlock optional unaligned xor buffer +/// \details UnalignedbyteNonTemplate writes a word16 value to an unaligned buffer. +/// \since Crypto++ 1.0 +inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + } + } +} + +/// \brief Write a word32 to an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned output buffer +/// \param value word32 value +/// \param xorBlock optional unaligned xor buffer +/// \details UnalignedbyteNonTemplate writes a word32 value to an unaligned buffer. +/// \since Crypto++ 1.0 +inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + } + } +} + +/// \brief Write a word64 to an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned output buffer +/// \param value word64 value +/// \param xorBlock optional unaligned xor buffer +/// \details UnalignedbyteNonTemplate writes a word64 value to an unaligned buffer. +/// \since Crypto++ 1.0 +inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + } + } +} + +#if defined(CRYPTOPP_WORD128_AVAILABLE) +/// \brief Write a word128 to an unaligned buffer +/// \param order the ByteOrder of the data +/// \param block an unaligned output buffer +/// \param value word128 value +/// \param xorBlock optional unaligned xor buffer +/// \details UnalignedbyteNonTemplate writes a word128 value to an unaligned buffer. +/// \note word128 is available on some 64-bit platforms when the compiler supports it. +/// \since Crypto++ 8.7 +inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, word128 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 15); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 14); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 13); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 12); + block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 11); + block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 10); + block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 9); + block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 8); + + block[ 8] = xorBlock[ 8] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + block[ 9] = xorBlock[ 9] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[10] = xorBlock[10] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[11] = xorBlock[11] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[12] = xorBlock[12] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[13] = xorBlock[13] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[14] = xorBlock[14] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[15] = xorBlock[15] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 15); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 14); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 13); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 12); + block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 11); + block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 10); + block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 9); + block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 8); + + block[ 8] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + block[ 9] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[10] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[11] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[12] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[13] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[14] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[15] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + + block[ 8] = xorBlock[ 8] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 8); + block[ 9] = xorBlock[ 9] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 9); + block[10] = xorBlock[10] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 10); + block[11] = xorBlock[11] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 11); + block[12] = xorBlock[12] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 12); + block[13] = xorBlock[13] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 13); + block[14] = xorBlock[14] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 14); + block[15] = xorBlock[15] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 15); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + + block[ 8] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 8); + block[ 9] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 9); + block[10] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 10); + block[11] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 11); + block[12] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 12); + block[13] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 13); + block[14] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 14); + block[15] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 15); + } + } +} +#endif + +/// \brief Access a block of memory +/// \tparam T class or type +/// \param assumeAligned flag indicating alignment +/// \param order the ByteOrder of the data +/// \param block the byte buffer to be processed +/// \return the word in the specified byte order +/// \details GetWord() provides alternate read access to a block of memory. The flag assumeAligned indicates +/// if the memory block is aligned for class or type T. The enumeration ByteOrder is BIG_ENDIAN_ORDER or +/// LITTLE_ENDIAN_ORDER. +/// \details An example of reading two word32 values from a block of memory is shown below. w +/// will be 0x03020100. +///
+///   word32 w;
+///   byte buffer[4] = {0,1,2,3};
+///   w = GetWord(false, LITTLE_ENDIAN_ORDER, buffer);
+/// 
+template +inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) +{ + CRYPTOPP_UNUSED(assumeAligned); + + T temp = 0; + if (block != NULLPTR) {std::memcpy(&temp, block, sizeof(T));} + return ConditionalByteReverse(order, temp); +} + +/// \brief Access a block of memory +/// \tparam T class or type +/// \param assumeAligned flag indicating alignment +/// \param order the ByteOrder of the data +/// \param result the word in the specified byte order +/// \param block the byte buffer to be processed +/// \details GetWord() provides alternate read access to a block of memory. The flag assumeAligned indicates +/// if the memory block is aligned for class or type T. The enumeration ByteOrder is BIG_ENDIAN_ORDER or +/// LITTLE_ENDIAN_ORDER. +/// \details An example of reading two word32 values from a block of memory is shown below. w +/// will be 0x03020100. +///
+///   word32 w;
+///   byte buffer[4] = {0,1,2,3};
+///   w = GetWord(false, LITTLE_ENDIAN_ORDER, buffer);
+/// 
+template +inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block) +{ + result = GetWord(assumeAligned, order, block); +} + +/// \brief Access a block of memory +/// \tparam T class or type +/// \param assumeAligned flag indicating alignment +/// \param order the ByteOrder of the data +/// \param block the destination byte buffer +/// \param value the word in the specified byte order +/// \param xorBlock an optional byte buffer to xor +/// \details PutWord() provides alternate write access to a block of memory. The flag assumeAligned indicates +/// if the memory block is aligned for class or type T. The enumeration ByteOrder is BIG_ENDIAN_ORDER or +/// LITTLE_ENDIAN_ORDER. +template +inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULLPTR) +{ + CRYPTOPP_UNUSED(assumeAligned); + + T t1, t2; + t1 = ConditionalByteReverse(order, value); + if (xorBlock != NULLPTR) {std::memcpy(&t2, xorBlock, sizeof(T)); t1 ^= t2;} + if (block != NULLPTR) {std::memcpy(block, &t1, sizeof(T));} +} + +/// \brief Access a block of memory +/// \tparam T class or type +/// \tparam B enumeration indicating endianness +/// \tparam A flag indicating alignment +/// \details GetBlock() provides alternate read access to a block of memory. The enumeration B is +/// BigEndian or LittleEndian. The flag A indicates if the memory block is aligned for class or type T. +/// Repeatedly applying operator() results in advancing in the block of memory. +/// \details An example of reading two word32 values from a block of memory is shown below. w1 +/// will be 0x03020100 and w1 will be 0x07060504. +///
+///   word32 w1, w2;
+///   byte buffer[8] = {0,1,2,3,4,5,6,7};
+///   GetBlock block(buffer);
+///   block(w1)(w2);
+/// 
+template +class GetBlock +{ +public: + /// \brief Construct a GetBlock + /// \param block the memory block + GetBlock(const void *block) + : m_block((const byte *)block) {} + + /// \brief Access a block of memory + /// \tparam U class or type + /// \param x the value to read + /// \return pointer to the remainder of the block after reading x + template + inline GetBlock & operator()(U &x) + { + CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T)); + x = GetWord(A, B::ToEnum(), m_block); + m_block += sizeof(T); + return *this; + } + +private: + const byte *m_block; +}; + +/// \brief Access a block of memory +/// \tparam T class or type +/// \tparam B enumeration indicating endianness +/// \tparam A flag indicating alignment +/// \details PutBlock() provides alternate write access to a block of memory. The enumeration B is +/// BigEndian or LittleEndian. The flag A indicates if the memory block is aligned for class or type T. +/// Repeatedly applying operator() results in advancing in the block of memory. +/// \details An example of writing two word32 values from a block of memory is shown below. After the code +/// executes, the byte buffer will be {0,1,2,3,4,5,6,7}. +///
+///   word32 w1=0x03020100, w2=0x07060504;
+///   byte buffer[8];
+///   PutBlock block(NULLPTR, buffer);
+///   block(w1)(w2);
+/// 
+template +class PutBlock +{ +public: + /// \brief Construct a PutBlock + /// \param block the memory block + /// \param xorBlock optional mask + PutBlock(const void *xorBlock, void *block) + : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {} + + /// \brief Access a block of memory + /// \tparam U class or type + /// \param x the value to write + /// \return pointer to the remainder of the block after writing x + template + inline PutBlock & operator()(U x) + { + PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock); + m_block += sizeof(T); + if (m_xorBlock) + m_xorBlock += sizeof(T); + return *this; + } + +private: + const byte *m_xorBlock; + byte *m_block; +}; + +/// \brief Access a block of memory +/// \tparam T class or type +/// \tparam B enumeration indicating endianness +/// \tparam GA flag indicating alignment for the Get operation +/// \tparam PA flag indicating alignment for the Put operation +/// \details GetBlock() provides alternate write access to a block of memory. The enumeration B is +/// BigEndian or LittleEndian. The flag A indicates if the memory block is aligned for class or type T. +/// \sa GetBlock() and PutBlock(). +template +struct BlockGetAndPut +{ + // function needed because of C++ grammatical ambiguity between expression-statements and declarations + static inline GetBlock Get(const void *block) {return GetBlock(block);} + typedef PutBlock Put; +}; + +/// \brief Convert a word to a string +/// \tparam T class or type +/// \param value the word to convert +/// \param order byte order +/// \return a string representing the value of the word +template +std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER) +{ + if (!NativeByteOrderIs(order)) + value = ByteReverse(value); + + return std::string((char *)&value, sizeof(value)); +} + +/// \brief Convert a string to a word +/// \tparam T class or type +/// \param str the string to convert +/// \param order byte order +/// \return a word representing the value of the string +template +T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER) +{ + T value = 0; + memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value))); + return NativeByteOrderIs(order) ? value : ByteReverse(value); +} + +// ************** help remove warning on g++ *************** + +/// \brief Safely shift values when undefined behavior could occur +/// \tparam overflow boolean flag indicating if overflow is present +/// \details SafeShifter safely shifts values when undefined behavior could occur under C/C++ rules. +/// The class behaves much like a saturating arithmetic class, clamping values rather than allowing +/// the compiler to remove undefined behavior. +/// \sa SafeShifter, SafeShifter +template struct SafeShifter; + +/// \brief Shifts a value in the presence of overflow +/// \details the true template parameter indicates overflow would occur. +/// In this case, SafeShifter clamps the value and returns 0. +template<> struct SafeShifter +{ + /// \brief Right shifts a value that overflows + /// \tparam T class or type + /// \return 0 + /// \details Since overflow == true, the value 0 is always returned. + /// \sa SafeLeftShift + template + static inline T RightShift(T value, unsigned int bits) + { + CRYPTOPP_UNUSED(value); CRYPTOPP_UNUSED(bits); + return 0; + } + + /// \brief Left shifts a value that overflows + /// \tparam T class or type + /// \return 0 + /// \details Since overflow == true, the value 0 is always returned. + /// \sa SafeRightShift + template + static inline T LeftShift(T value, unsigned int bits) + { + CRYPTOPP_UNUSED(value); CRYPTOPP_UNUSED(bits); + return 0; + } +}; + +/// \brief Shifts a value in the absence of overflow +/// \details the false template parameter indicates overflow would not occur. +/// In this case, SafeShifter returns the shfted value. +template<> struct SafeShifter +{ + /// \brief Right shifts a value that does not overflow + /// \tparam T class or type + /// \return the shifted value + /// \details Since overflow == false, the shifted value is returned. + /// \sa SafeLeftShift + template + static inline T RightShift(T value, unsigned int bits) + { + return value >> bits; + } + + /// \brief Left shifts a value that does not overflow + /// \tparam T class or type + /// \return the shifted value + /// \details Since overflow == false, the shifted value is returned. + /// \sa SafeRightShift + template + static inline T LeftShift(T value, unsigned int bits) + { + return value << bits; + } +}; + +/// \brief Safely right shift values when undefined behavior could occur +/// \tparam bits the number of bit positions to shift the value +/// \tparam T class or type +/// \param value the value to right shift +/// \result the shifted value or 0 +/// \details SafeRightShift safely shifts the value to the right when undefined behavior +/// could occur under C/C++ rules. SafeRightShift will return the shifted value or 0 +/// if undefined behavior would occur. +template +inline T SafeRightShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); +} + +/// \brief Safely left shift values when undefined behavior could occur +/// \tparam bits the number of bit positions to shift the value +/// \tparam T class or type +/// \param value the value to left shift +/// \result the shifted value or 0 +/// \details SafeLeftShift safely shifts the value to the left when undefined behavior +/// could occur under C/C++ rules. SafeLeftShift will return the shifted value or 0 +/// if undefined behavior would occur. +template +inline T SafeLeftShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits); +} + +/// \brief Finds first element not in a range +/// \tparam InputIt Input iterator type +/// \tparam T class or type +/// \param first iterator to first element +/// \param last iterator to last element +/// \param value the value used as a predicate +/// \return iterator to the first element in the range that is not value +template +inline InputIt FindIfNot(InputIt first, InputIt last, const T &value) { +#ifdef CRYPTOPP_CXX11_LAMBDA + return std::find_if(first, last, [&value](const T &o) { + return value!=o; + }); +#else + return std::find_if(first, last, std::bind2nd(std::not_equal_to(), value)); +#endif +} + +// ************** use one buffer for multiple data members *************** + +#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+0);} size_t SS1() {return sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(void *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate; + +NAMESPACE_END + +#if (CRYPTOPP_MSC_VERSION) +# pragma warning(pop) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/modarith.h b/third_party/cryptoppwin/include/cryptopp/modarith.h new file mode 100644 index 00000000..408f4caf --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/modarith.h @@ -0,0 +1,344 @@ +// modarith.h - originally written and placed in the public domain by Wei Dai + +/// \file modarith.h +/// \brief Class file for performing modular arithmetic. + +#ifndef CRYPTOPP_MODARITH_H +#define CRYPTOPP_MODARITH_H + +// implementations are in integer.cpp + +#include "cryptlib.h" +#include "integer.h" +#include "algebra.h" +#include "secblock.h" +#include "misc.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; + +/// \brief Ring of congruence classes modulo n +/// \details This implementation represents each congruence class as +/// the smallest non-negative integer in that class. +/// \details const Element& returned by member functions are +/// references to internal data members. Since each object may have +/// only one such data member for holding results, you should use the +/// class like this: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+/// The following code will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// \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 Integer on the +/// Crypto++ wiki. +class CRYPTOPP_DLL ModularArithmetic : public AbstractRing +{ +public: + + typedef int RandomizationParameter; + typedef Integer Element; + + virtual ~ModularArithmetic() {} + + /// \brief Construct a ModularArithmetic + /// \param modulus congruence class modulus + ModularArithmetic(const Integer &modulus = Integer::One()) + : m_modulus(modulus), m_result(static_cast(0), modulus.reg.size()) {} + + /// \brief Copy construct a ModularArithmetic + /// \param ma other ModularArithmetic + ModularArithmetic(const ModularArithmetic &ma) + : AbstractRing(ma), m_modulus(ma.m_modulus), m_result(static_cast(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(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 + /// \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);} + + /// \brief Encodes in DER format + /// \param bt BufferedTransformation object + void DEREncode(BufferedTransformation &bt) const; + + /// \brief Encodes element in DER format + /// \param out BufferedTransformation object + /// \param a Element to encode + void DEREncodeElement(BufferedTransformation &out, const Element &a) const; + + /// \brief Decodes element in DER format + /// \param in BufferedTransformation object + /// \param a Element to decode + void BERDecodeElement(BufferedTransformation &in, Element &a) const; + + /// \brief Retrieves the modulus + /// \return the modulus + const Integer& GetModulus() const {return m_modulus;} + + /// \brief Sets the modulus + /// \param newModulus the new modulus + void SetModulus(const Integer &newModulus) + {m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());} + + /// \brief Retrieves the representation + /// \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 + /// \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 + {return a%m_modulus;} + + /// \brief Reduces an element in the congruence class + /// \param a element to convert + /// \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 + {return a;} + + /// \brief Divides an element by 2 + /// \param a element to convert + const Integer& Half(const Integer &a) const; + + /// \brief Compare two elements for equality + /// \param a first element + /// \param b second element + /// \return true if the elements are equal, false otherwise + /// \details Equal() tests the elements for equality using a==b + bool Equal(const Integer &a, const Integer &b) const + {return a==b;} + + /// \brief Provides 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 + /// \return the sum of a and b + const Integer& Add(const Integer &a, const Integer &b) const; + + /// \brief TODO + /// \param a first element + /// \param b second element + /// \return TODO + Integer& Accumulate(Integer &a, const Integer &b) const; + + /// \brief Inverts the element in the ring + /// \param a first 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 + /// \return the difference of a and b. The element a 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 + /// \return TODO + Integer& Reduce(Integer &a, const Integer &b) const; + + /// \brief Doubles an element in the ring + /// \param a the element + /// \return the element doubled + /// \details Double returns Add(a, a). The element a must provide an Add member function. + const Integer& Double(const Integer &a) const + {return Add(a, a);} + + /// \brief Retrieves the multiplicative identity + /// \return the multiplicative identity + /// \details the base class implementations returns 1. + const Integer& MultiplicativeIdentity() const + {return Integer::One();} + + /// \brief Multiplies elements in the ring + /// \param a the multiplicand + /// \param b the multiplier + /// \return the product of a and b + /// \details Multiply returns a*b\%n. + 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 + /// \return the element squared + /// \details Square returns a*a\%n. The element a 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 + /// \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();} + + /// \brief Calculate the multiplicative inverse of an element in the ring + /// \param a the element + /// \details MultiplicativeInverse returns a-1\%n. The element a must + /// provide a InverseMod member function. + const Integer& MultiplicativeInverse(const Integer &a) const + {return m_result1 = a.InverseMod(m_modulus);} + + /// \brief Divides elements in the ring + /// \param a the dividend + /// \param b the divisor + /// \return the quotient + /// \details Divide returns a*b-1\%n. + const Integer& Divide(const Integer &a, const Integer &b) const + {return Multiply(a, MultiplicativeInverse(b));} + + /// \brief TODO + /// \param x first element + /// \param e1 first exponent + /// \param y second element + /// \param e2 second exponent + /// \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 + /// \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 COUNTOF(results) == exponentsCount + /// \pre COUNTOF(exponents) == exponentsCount + 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 + /// \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 + /// \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 + /// \return a random element that is uniformly distributed + /// \details RandomElement constructs a new element in the range [0,n-1], inclusive. + /// The element's class must provide a constructor with the signature Element(RandomNumberGenerator rng, + /// Element min, Element max). + 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); + return Element(rng, Integer::Zero(), m_modulus - Integer::One()) ; + } + + /// \brief Compares two ModularArithmetic for equality + /// \param rhs other ModularArithmetic + /// \return true if this is equal to the other, false otherwise + /// \details The operator tests for equality using this.m_modulus == rhs.m_modulus. + bool operator==(const ModularArithmetic &rhs) const + {return m_modulus == rhs.m_modulus;} + + 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; + mutable Integer m_result, m_result1; +}; + +// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ; + +/// \brief Performs modular arithmetic in Montgomery representation for increased speed +/// \details The Montgomery representation represents each congruence class [a] as +/// a*r\%n, where r is a convenient power of 2. +/// \details const Element& returned by member functions are references to +/// internal data members. Since each object may have only one such data member for holding +/// results, the following code will produce incorrect results: +///
    abcd = group.Add(group.Add(a,b), group.Add(c,d));
+/// But this should be fine: +///
    abcd = group.Add(a, group.Add(b, group.Add(c,d));
+class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic +{ +public: + virtual ~MontgomeryRepresentation() {} + + /// \brief Construct a MontgomeryRepresentation + /// \param modulus congruence class modulus + /// \note The modulus must be odd. + MontgomeryRepresentation(const Integer &modulus); + + /// \brief Clone a 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);} + + bool IsMontgomeryRepresentation() const {return true;} + + Integer ConvertIn(const Integer &a) const + {return (a<<(WORD_BITS*m_modulus.reg.size()))%m_modulus;} + + Integer ConvertOut(const Integer &a) const; + + const Integer& MultiplicativeIdentity() const + {return m_result1 = Integer::Power2(WORD_BITS*m_modulus.reg.size())%m_modulus;} + + const Integer& Multiply(const Integer &a, const Integer &b) const; + + const Integer& Square(const Integer &a) const; + + const Integer& MultiplicativeInverse(const Integer &a) const; + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const + {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const + {AbstractRing::SimultaneousExponentiate(results, base, exponents, exponentsCount);} + +private: + Integer m_u; + mutable IntegerSecBlock m_workspace; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/modes.h b/third_party/cryptoppwin/include/cryptopp/modes.h new file mode 100644 index 00000000..24126980 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/modes.h @@ -0,0 +1,609 @@ +// modes.h - originally written and placed in the public domain by Wei Dai + +/// \file modes.h +/// \brief Classes for block cipher modes of operation + +#ifndef CRYPTOPP_MODES_H +#define CRYPTOPP_MODES_H + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" +#include "strciphr.h" +#include "argnames.h" +#include "algparam.h" + +// Issue 340 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6011 6386 28193) +# endif +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Block cipher mode of operation information +/// \details Each class derived from this one defines two types, Encryption and Decryption, +/// both of which implement the SymmetricCipher interface. +/// For each mode there are two classes, one of which is a template class, +/// and the other one has a name that ends in "_ExternalCipher". +/// The "external cipher" mode objects hold a reference to the underlying block cipher, +/// instead of holding an instance of it. The reference must be passed in to the constructor. +/// For the "cipher holder" classes, the CIPHER template parameter should be a class +/// derived from BlockCipherDocumentation, for example DES or AES. +/// \details See NIST SP 800-38A for definitions of these modes. See +/// AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes. +struct CipherModeDocumentation : public SymmetricCipherDocumentation +{ +}; + +/// \brief Block cipher mode of operation information +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();} + + /// \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(); + this->m_cipher = &cipher; + 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); + this->m_cipher = &cipher; + this->ResizeBuffers(); + this->SetFeedbackSize(feedbackSize); + if (this->IsResynchronizable()) + this->Resynchronize(iv); + } + +protected: + CipherModeBase() : m_cipher(NULLPTR) {} + inline unsigned int BlockSize() const + { + CRYPTOPP_ASSERT(m_register.size() > 0); + return static_cast(m_register.size()); + } + virtual void SetFeedbackSize(unsigned int feedbackSize) + { + if (!(feedbackSize == 0 || feedbackSize == BlockSize())) + throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode"); + } + + virtual void ResizeBuffers(); + + BlockCipher *m_cipher; + SecByteBlock m_register; +}; + +/// \brief Block cipher mode of operation common operations +/// \tparam POLICY_INTERFACE common operations +template +class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE +{ + unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); +}; + +template +void ModePolicyCommonTemplate::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + m_cipher->SetKey(key, length, params); + ResizeBuffers(); + int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0); + SetFeedbackSize(feedbackSize); +} + +/// \brief CFB block cipher mode of operation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate +{ +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;} + 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; +}; + +/// \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(dsize >= ssize); + + if (src != NULLPTR) + memcpy_s(dest, dsize, src, ssize); + else + std::memset(dest, 0, dsize); +} + +/// \brief OFB block cipher mode of operation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "OFB";} + + bool CipherIsRandomAccess() const {return false;} + IV_Requirement IVRequirement() const {return UNIQUE_IV;} + +protected: + unsigned int GetBytesPerIteration() const {return BlockSize();} + unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} + void WriteKeystream(byte *keystreamBuffer, size_t iterationCount); + void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); +}; + +/// \brief CTR block cipher mode of operation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "CTR";} + + virtual ~CTR_ModePolicy() {} + bool CipherIsRandomAccess() const {return true;} + IV_Requirement IVRequirement() const {return RANDOM_IV;} + +protected: + virtual void IncrementCounterBy256(); + unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} + unsigned int GetBytesPerIteration() const {return BlockSize();} + unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} + void WriteKeystream(byte *buffer, size_t iterationCount) + {OperateKeystream(WRITE_KEYSTREAM, buffer, NULLPTR, iterationCount);} + bool CanOperateKeystream() const {return true;} + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); + void SeekToIteration(lword iterationCount); + + // adv_simd.h increments the counter + mutable SecByteBlock m_counterArray; +}; + +/// \brief Block cipher mode of operation default implementation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase +{ +public: + virtual ~BlockOrientedCipherModeBase() {} + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + 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));} + +protected: + bool RequireAlignedInput() const {return true;} + virtual void ResizeBuffers(); + + SecByteBlock m_buffer; +}; + +/// \brief ECB block cipher mode of operation default implementation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "ECB";} + + void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs) + {m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();} + IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;} + unsigned int OptimalBlockSize() const {return static_cast(BlockSize() * m_cipher->OptimalNumberOfParallelBlocks());} + void ProcessData(byte *outString, const byte *inString, size_t length); +}; + +/// \brief CBC block cipher mode of operation default implementation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "CBC";} + + IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;} + bool RequireAlignedInput() const {return false;} + unsigned int MinLastBlockSize() const {return 0;} +}; + +/// \brief CBC block cipher mode of operation encryption operation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase +{ +public: + void ProcessData(byte *outString, const byte *inString, size_t length); +}; + +/// \brief CBC-CTS block cipher mode of operation encryption operation +/// \since Crypto++ 3.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";} + + void SetStolenIV(byte *iv) {m_stolenIV = iv;} + unsigned int MinLastBlockSize() const {return BlockSize()+1;} + size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); + +protected: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) + { + CBC_Encryption::UncheckedSetKey(key, length, params); + m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), static_cast(NULLPTR)); + } + + byte *m_stolenIV; +}; + +/// \brief CBC block cipher mode of operation decryption operation +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase +{ +public: + virtual ~CBC_Decryption() {} + void ProcessData(byte *outString, const byte *inString, size_t length); + +protected: + virtual void ResizeBuffers(); + + SecByteBlock m_temp; +}; + +/// \brief CBC-CTS block cipher mode of operation decryption operation +/// \since Crypto++ 3.0 +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption +{ +public: + unsigned int MinLastBlockSize() const {return BlockSize()+1;} + size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); +}; + +/// \brief Block cipher mode of operation aggregate +template +class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder, public AlgorithmImpl > +{ +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 +/// \details Base class for external mode cipher combinations +template +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 >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; + +/// \brief CFB block cipher mode of operation +/// \sa Modes of Operation +/// on the Crypto++ wiki. +template +struct CFB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > > > Decryption; +}; + +/// \brief CFB mode, external cipher. +/// \sa Modes of Operation +/// on the Crypto++ wiki. +struct CFB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef CipherModeFinalTemplate_ExternalCipher > > > Decryption; +}; + +/// \brief CFB block cipher mode of operation providing FIPS validated cryptography. +/// \details Requires full block plaintext according to FIPS 800-38A +/// \sa Modes of Operation +/// on the Crypto++ wiki. +template +struct CFB_FIPS_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > > > > Decryption; +}; + +/// \brief CFB mode, external cipher, providing FIPS validated cryptography. +/// \details Requires full block plaintext according to FIPS 800-38A +/// \sa Modes of Operation +/// on the Crypto++ wiki. +struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > > Encryption; + typedef CipherModeFinalTemplate_ExternalCipher > > > > Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; + +/// \brief OFB block cipher mode of operation +/// \sa Modes of Operation +/// on the Crypto++ wiki. +template +struct OFB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef Encryption Decryption; +}; + +/// \brief OFB mode, external cipher. +/// \sa Modes of Operation +/// on the Crypto++ wiki. +struct OFB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef Encryption Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher > > >; + +/// \brief CTR block cipher mode of operation +/// \sa Modes of Operation +/// on the Crypto++ wiki. +template +struct CTR_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef Encryption Decryption; +}; + +/// \brief CTR mode, external cipher. +/// \sa Modes of Operation +/// on the Crypto++ wiki. +struct CTR_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef Encryption Decryption; +}; + +/// \brief ECB block cipher mode of operation +/// \sa Modes of Operation +/// on the Crypto++ wiki. +template +struct ECB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +/// \brief ECB mode, external cipher. +/// \sa Modes of Operation +/// on the Crypto++ wiki. +struct ECB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef Encryption Decryption; +}; + +/// \brief CBC block cipher mode of operation +/// \sa Modes of Operation +/// on the Crypto++ wiki. +template +struct CBC_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +/// \brief CBC mode, external cipher +/// \sa Modes of Operation +/// on the Crypto++ wiki. +struct CBC_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef CipherModeFinalTemplate_ExternalCipher Decryption; +}; + +/// \brief CBC-CTS block cipher mode of operation +/// \sa Modes of Operation +/// on the Crypto++ wiki. +/// \since Crypto++ 3.0 +template +struct CBC_CTS_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +/// \brief CBC mode with ciphertext stealing, external cipher +/// \sa Modes of Operation +/// on the Crypto++ wiki. +/// \since Crypto++ 3.0 +struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef CipherModeFinalTemplate_ExternalCipher Decryption; +}; + +NAMESPACE_END + +// Issue 340 +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/modexppc.h b/third_party/cryptoppwin/include/cryptopp/modexppc.h new file mode 100644 index 00000000..cacb0aa6 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/modexppc.h @@ -0,0 +1,48 @@ +#ifndef CRYPTOPP_MODEXPPC_H +#define CRYPTOPP_MODEXPPC_H + +#include "cryptlib.h" +#include "modarith.h" +#include "integer.h" +#include "algebra.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4231 4275) +#endif + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; + +class ModExpPrecomputation : public DL_GroupPrecomputation +{ +public: + virtual ~ModExpPrecomputation() {} + + // DL_GroupPrecomputation + bool NeedConversions() const {return true;} + Element ConvertIn(const Element &v) const {return m_mr->ConvertIn(v);} + virtual Element ConvertOut(const Element &v) const {return m_mr->ConvertOut(v);} + const AbstractGroup & GetGroup() const {return m_mr->MultiplicativeGroup();} + Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);} + + // non-inherited + void SetModulus(const Integer &v) {m_mr.reset(new MontgomeryRepresentation(v));} + const Integer & GetModulus() const {return m_mr->GetModulus();} + +private: + value_ptr m_mr; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/mqueue.h b/third_party/cryptoppwin/include/cryptopp/mqueue.h new file mode 100644 index 00000000..632ae295 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/mqueue.h @@ -0,0 +1,145 @@ +// 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 + +#include "cryptlib.h" +#include "queue.h" +#include "filters.h" +#include "misc.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Data structure used to store messages +/// \details The queue is implemented with a ByteQueue. +/// \sa MessageQueue +/// on the Crypto++ wiki. +/// \since Crypto++ 2.0 +class CRYPTOPP_DLL MessageQueue : public AutoSignaling +{ +public: + virtual ~MessageQueue() {} + + /// \brief Construct a MessageQueue + /// \param nodeSize the initial node size + MessageQueue(unsigned int nodeSize=256); + + // BufferedTransformation + void IsolatedInitialize(const NameValuePairs ¶meters) + {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) + { + CRYPTOPP_UNUSED(blocking); + m_queue.Put(begin, length); + m_lengths.back() += length; + if (messageEnd) + { + m_lengths.push_back(0); + m_messageCounts.back()++; + } + return 0; + } + bool IsolatedFlush(bool hardFlush, bool blocking) + {CRYPTOPP_UNUSED(hardFlush), CRYPTOPP_UNUSED(blocking); return false;} + bool IsolatedMessageSeriesEnd(bool blocking) + {CRYPTOPP_UNUSED(blocking); m_messageCounts.push_back(0); return false;} + + lword MaxRetrievable() const + {return m_lengths.front();} + bool AnyRetrievable() const + {return m_lengths.front() > 0;} + + 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; + + lword TotalBytesRetrievable() const + {return m_queue.MaxRetrievable();} + unsigned int NumberOfMessages() const + {return (unsigned int)m_lengths.size()-1;} + bool GetNextMessage(); + + unsigned int NumberOfMessagesInThisSeries() const + {return m_messageCounts[0];} + 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 contiguousSize. + /// 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: + ByteQueue m_queue; + std::deque m_lengths; + std::deque m_messageCounts; +}; + +/// \brief Filter that checks messages on two channels for equality +class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable > +{ +public: + /// \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); + +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]; +}; + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/mqv.h b/third_party/cryptoppwin/include/cryptopp/mqv.h new file mode 100644 index 00000000..8e25b9cf --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/mqv.h @@ -0,0 +1,268 @@ +// mqv.h - originally written and placed in the public domain by Wei Dai + +/// \file mqv.h +/// \brief Classes for Menezes–Qu–Vanstone (MQV) key agreement +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_MQV_H +#define CRYPTOPP_MQV_H + +#include "cryptlib.h" +#include "gfpcrypt.h" +#include "modarith.h" +#include "integer.h" +#include "algebra.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief MQV domain for performing authenticated key agreement +/// \tparam GROUP_PARAMETERS doamin parameters +/// \tparam COFACTOR_OPTION cofactor option +/// \details GROUP_PARAMETERS parameters include the curve coefcients and the base point. +/// Binary curves use a polynomial to represent its characteristic, while prime curves +/// use a prime number. +/// \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain +/// \since Crypto++ 3.0 +template +class MQV_Domain : public AuthenticatedKeyAgreementDomain +{ +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef MQV_Domain Domain; + + /// \brief Construct a MQV domain + MQV_Domain() {} + + /// \brief Construct a MQV domain + /// \param params group parameters and options + MQV_Domain(const GroupParameters ¶ms) + : m_groupParameters(params) {} + + /// \brief Construct a MQV domain + /// \param bt BufferedTransformation with group parameters and options + MQV_Domain(BufferedTransformation &bt) + {m_groupParameters.BERDecode(bt);} + + /// \brief Construct a MQV 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 + /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object. + template + MQV_Domain(T1 v1, T2 v2) + {m_groupParameters.Initialize(v1, v2);} + + /// \brief Construct a MQV 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 + /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object. + template + MQV_Domain(T1 v1, T2 v2, T3 v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + /// \brief Construct a MQV 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 + /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object. + template + MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + /// \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;} + + /// \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 GetEncodedElementSize(false), + /// 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 GetEncodedElementSize(true), + /// 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 + /// [1,MaxExponent()]. + /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength() + void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + } + + /// \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 COUNTOF(publicKey) == PublicStaticKeyLength() + void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + 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 COUNTOF(privateKey) == EphemeralPrivateKeyLength() + void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(rng, Integer::One(), params.GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + 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 COUNTOF(publicKey) == EphemeralPublicKeyLength() + void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + 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. + /// validateStaticOtherPublicKey determines how thoroughly other's + /// static public key is validated. If you have previously validated the + /// couterparty's static public key, then use + /// validateStaticOtherPublicKey=false to save time. + /// \pre COUNTOF(agreedValue) == AgreedValueLength() + /// \pre COUNTOF(staticPrivateKey) == StaticPrivateKeyLength() + /// \pre COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength() + /// \pre COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength() + /// \pre COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength() + bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const + { + try + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey); + Element VV = params.DecodeElement(ephemeralOtherPublicKey, true); + + Integer s(staticPrivateKey, StaticPrivateKeyLength()); + Integer u(ephemeralPrivateKey, StaticPrivateKeyLength()); + Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false); + + const Integer &r = params.GetSubgroupOrder(); + Integer h2 = Integer::Power2((r.BitCount()+1)/2); + Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r; + Integer tt = h2 + params.ConvertElementToInteger(VV) % h2; + + if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION) + { + Element P = params.ExponentiateElement(WW, tt); + P = m_groupParameters.MultiplyElements(P, VV); + Element R[2]; + const Integer e2[2] = {r, e}; + params.SimultaneousExponentiate(R, P, e2, 2); + if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1])) + return false; + params.EncodeElement(false, R[1], agreedValue); + } + else + { + const Integer &k = params.GetCofactor(); + if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) + e = ModularArithmetic(r).Divide(e, k); + Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r)); + if (params.IsIdentity(P)) + return false; + params.EncodeElement(false, P, agreedValue); + } + } + catch (DL_BadElement &) + { + return false; + } + return true; + } + +private: + DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} + const DL_GroupParameters & GetAbstractGroupParameters() const {return m_groupParameters;} + + GroupParameters m_groupParameters; +}; + +/// Menezes-Qu-Vanstone in GF(p) with key validation, AKA MQV +/// \sa MQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain +/// \since Crypto++ 3.0 +typedef MQV_Domain MQV; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/naclite.h b/third_party/cryptoppwin/include/cryptopp/naclite.h new file mode 100644 index 00000000..efb542cd --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/naclite.h @@ -0,0 +1,438 @@ +// naclite.h - written and placed in the public domain by Jeffrey Walton +// based on public domain NaCl source code written by +// 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 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 TweetNaCl: +/// A crypto library in 100 tweets (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 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, +/// NO_OS_DEPENDENCE cannot be defined. It is due to TweetNaCl's +/// internal function randombytes. Crypto++ used +/// DefaultAutoSeededRNG within randombytes, so OS +/// integration must be enabled. You can use another generator like +/// RDRAND to avoid the restriction. +/// \sa The security +/// impact of a new cryptographic library, TweetNaCl: +/// A crypto library in 100 tweets (20140917), May the Fourth Be With You: +/// A Microarchitectural Side Channel Attack on Several Real-World +/// Applications of Curve25519, libsodium +/// commit afabd7e7386e1194 and RFC 7748, Elliptic Curves for +/// Security, Section 6. +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_NACL_H +#define CRYPTOPP_NACL_H + +#include "config.h" +#include "stdcpp.h" + +#if defined(NO_OS_DEPENDENCE) || !defined(OS_RNG_AVAILABLE) +# define CRYPTOPP_DISABLE_NACL 1 +#endif + +#ifndef CRYPTOPP_DISABLE_NACL + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(NaCl) + +/// \brief Hash size in bytes +/// \sa NaCl crypto_hash documentation +CRYPTOPP_CONSTANT(crypto_hash_BYTES = 64); + +/// \brief Key size in bytes +/// \sa NaCl crypto_stream documentation +CRYPTOPP_CONSTANT(crypto_stream_KEYBYTES = 32); +/// \brief Nonce size in bytes +/// \sa NaCl crypto_stream documentation +CRYPTOPP_CONSTANT(crypto_stream_NONCEBYTES = 24); + +/// \brief Key size in bytes +/// \sa NaCl crypto_auth documentation +CRYPTOPP_CONSTANT(crypto_auth_KEYBYTES = 32); +/// \brief Tag size in bytes +/// \sa NaCl crypto_auth documentation +CRYPTOPP_CONSTANT(crypto_auth_BYTES = 16); + +/// \brief Key size in bytes +/// \sa NaCl crypto_onetimeauth documentation +CRYPTOPP_CONSTANT(crypto_onetimeauth_KEYBYTES = 32); +/// \brief Tag size in bytes +/// \sa NaCl crypto_onetimeauth documentation +CRYPTOPP_CONSTANT(crypto_onetimeauth_BYTES = 16); + +/// \brief Key size in bytes +/// \sa NaCl crypto_secretbox documentation +CRYPTOPP_CONSTANT(crypto_secretbox_KEYBYTES = 32); +/// \brief Nonce size in bytes +/// \sa NaCl crypto_secretbox documentation +CRYPTOPP_CONSTANT(crypto_secretbox_NONCEBYTES = 24); +/// \brief Zero-padded message prefix in bytes +/// \sa NaCl crypto_secretbox documentation +CRYPTOPP_CONSTANT(crypto_secretbox_ZEROBYTES = 32); +/// \brief Zero-padded message prefix in bytes +/// \sa NaCl crypto_secretbox documentation +CRYPTOPP_CONSTANT(crypto_secretbox_BOXZEROBYTES = 16); + +/// \brief Private key size in bytes +/// \sa NaCl crypto_box documentation +CRYPTOPP_CONSTANT(crypto_box_SECRETKEYBYTES = 32); +/// \brief Public key size in bytes +/// \sa NaCl crypto_box documentation +CRYPTOPP_CONSTANT(crypto_box_PUBLICKEYBYTES = 32); +/// \brief Nonce size in bytes +/// \sa NaCl crypto_box documentation +CRYPTOPP_CONSTANT(crypto_box_NONCEBYTES = 24); +/// \brief Message 0-byte prefix in bytes +/// \sa NaCl crypto_box documentation +CRYPTOPP_CONSTANT(crypto_box_ZEROBYTES = 32); +/// \brief Open box 0-byte prefix in bytes +/// \sa NaCl crypto_box documentation +CRYPTOPP_CONSTANT(crypto_box_BOXZEROBYTES = 16); +/// \brief Precomputation 0-byte prefix in bytes in bytes +/// \sa NaCl crypto_box documentation +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 NaCl crypto_box documentation +CRYPTOPP_CONSTANT(crypto_box_MACBYTES = 16); + +/// \brief Private key size in bytes +/// \sa NaCl crypto_sign documentation +CRYPTOPP_CONSTANT(crypto_sign_SECRETKEYBYTES = 64); +/// \brief Public key size in bytes +/// \sa NaCl crypto_sign documentation +CRYPTOPP_CONSTANT(crypto_sign_PUBLICKEYBYTES = 32); +/// \brief Seed size in bytes +/// \sa NaCl crypto_sign documentation +CRYPTOPP_CONSTANT(crypto_sign_SEEDBYTES = 32); +/// \brief Signature size in bytes +/// \sa NaCl crypto_sign documentation +CRYPTOPP_CONSTANT(crypto_sign_BYTES = 64); + +/// \brief Group element size in bytes +/// \sa NaCl crypto_scalarmult documentation +CRYPTOPP_CONSTANT(crypto_scalarmult_BYTES = 32); +/// \brief Integer size in bytes +/// \sa NaCl crypto_scalarmult documentation +CRYPTOPP_CONSTANT(crypto_scalarmult_SCALARBYTES = 32); + +/// \brief Encrypt and authenticate a message +/// \param c output byte buffer +/// \param m input byte buffer +/// \param d size of the input byte buffer +/// \param n nonce byte buffer +/// \param y other's public key +/// \param x private key +/// \details crypto_box() uses crypto_box_curve25519xsalsa20poly1305 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_box documentation +/// \since Crypto++ 6.0 +int crypto_box(byte *c,const byte *m,word64 d,const byte *n,const byte *y,const byte *x); + +/// \brief Verify and decrypt a message +/// \param m output byte buffer +/// \param c input byte buffer +/// \param d size of the input byte buffer +/// \param n nonce byte buffer +/// \param y other's public key +/// \param x private key +/// \details crypto_box_open() uses crypto_box_curve25519xsalsa20poly1305 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_box documentation +/// \since Crypto++ 6.0 +int crypto_box_open(byte *m,const byte *c,word64 d,const byte *n,const byte *y,const byte *x); + +/// \brief Generate a keypair for encryption +/// \param y public key byte buffer +/// \param x private key byte buffer +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_box documentation +/// \since Crypto++ 6.0 +int crypto_box_keypair(byte *y,byte *x); + +/// \brief Encrypt and authenticate a message +/// \param k shared secret byte buffer +/// \param y other's public key +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_box documentation +/// \since Crypto++ 6.0 +int crypto_box_beforenm(byte *k,const byte *y,const byte *x); + +/// \brief Encrypt and authenticate a message +/// \param m output byte buffer +/// \param c input byte buffer +/// \param d size of the input byte buffer +/// \param n nonce byte buffer +/// \param k shared secret byte buffer +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_box documentation +/// \since Crypto++ 6.0 +int crypto_box_afternm(byte *c,const byte *m,word64 d,const byte *n,const byte *k); + +/// \brief Verify and decrypt a message +/// \param m output byte buffer +/// \param c input byte buffer +/// \param d size of the input byte buffer +/// \param n nonce byte buffer +/// \param k shared secret byte buffer +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_box documentation +/// \since Crypto++ 6.0 +int crypto_box_open_afternm(byte *m,const byte *c,word64 d,const byte *n,const byte *k); + +/// \brief Encrypt and authenticate a message +/// \param c output byte buffer +/// \param m input byte buffer +/// \param d size of the input byte buffer +/// \param n nonce byte buffer +/// \param y other's public key +/// \param x private key +/// \details crypto_box() uses crypto_box_curve25519xsalsa20poly1305. +/// \details This version of crypto_box() does not check for small order elements. It can be unsafe +/// but it exists for backwards compatibility with downlevel clients. Without the compatibility +/// 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. +/// \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 NaCl crypto_box documentation, +/// May the Fourth Be With You: A Microarchitectural +/// Side Channel Attack on Several Real-World Applications of Curve25519, +/// libsodium commit +/// afabd7e7386e1194. +/// \since Crypto++ 6.0 +int crypto_box_unchecked(byte *c,const byte *m,word64 d,const byte *n,const byte *y,const byte *x); + +/// \brief Verify and decrypt a message +/// \param m output byte buffer +/// \param c input byte buffer +/// \param d size of the input byte buffer +/// \param n nonce byte buffer +/// \param y other's public key +/// \param x private key +/// \details crypto_box_open() uses crypto_box_curve25519xsalsa20poly1305. +/// \details This version of crypto_box_open() does not check for small order elements. It can be unsafe +/// but it exists for backwards compatibility with downlevel clients. Without the compatibility +/// 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. +/// \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 NaCl crypto_box documentation, +/// May the Fourth Be With You: A Microarchitectural +/// Side Channel Attack on Several Real-World Applications of Curve25519, +/// libsodium commit +/// afabd7e7386e1194. +/// \since Crypto++ 6.0 +int crypto_box_open_unchecked(byte *m,const byte *c,word64 d,const byte *n,const byte *y,const byte *x); + +/// \brief Encrypt and authenticate a message +/// \param k shared secret byte buffer +/// \param y other's public key +/// \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. +/// \details This version of crypto_box_beforenm() does not check for small order elements. It can be unsafe +/// but it exists for backwards compatibility with downlevel clients. Without the compatibility +/// 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. +/// \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 NaCl crypto_box documentation, +/// May the Fourth Be With You: A Microarchitectural +/// Side Channel Attack on Several Real-World Applications of Curve25519, +/// libsodium commit +/// afabd7e7386e1194. +/// \since Crypto++ 6.0 +int crypto_box_beforenm_unchecked(byte *k,const byte *y,const byte *x); + +/// \brief TODO +int crypto_core_salsa20(byte *out,const byte *in,const byte *k,const byte *c); + +/// \brief TODO +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_hash documentation +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_hash documentation +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_onetimeauth documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_onetimeauth documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_scalarmult documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_scalarmult documentation +/// \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. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_secretbox documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_secretbox documentation +/// \since Crypto++ 6.0 +int crypto_secretbox_open(byte *m,const byte *c,word64 d,const byte *n,const byte *k); + +/// \brief Sign a message +/// \param sm output byte buffer +/// \param smlen size of the output byte buffer +/// \param m input byte buffer +/// \param n size of the input byte buffer +/// \param sk private key +/// \details crypto_sign() uses crypto_sign_ed25519. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_sign documentation +/// \since Crypto++ 6.0 +int crypto_sign(byte *sm,word64 *smlen,const byte *m,word64 n,const byte *sk); + +/// \brief Verify a message +/// \param m output byte buffer +/// \param mlen size of the output byte buffer +/// \param sm input byte buffer +/// \param n size of the input byte buffer +/// \param pk public key +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_sign documentation +/// \since Crypto++ 6.0 +int crypto_sign_open(byte *m,word64 *mlen,const byte *sm,word64 n,const byte *pk); + +/// \brief Generate a keypair for signing +/// \param pk public key byte buffer +/// \param sk private key byte buffer +/// \details crypto_sign_keypair() creates an ed25519 keypair. +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_sign documentation +/// \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 NaCl crypto_sign documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_stream documentation +/// \since Crypto++ 6.0 +int crypto_stream(byte *c,word64 d,const byte *n,const byte *k); + +/// \brief Encrypt a message using XSalsa20 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_stream documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_stream documentation +/// \since Crypto++ 6.0 +int crypto_stream_salsa20(byte *c,word64 d,const byte *n,const byte *k); + +/// \brief Encrypt a message using Salsa20 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_stream documentation +/// \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 +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_verify documentation +/// \since Crypto++ 6.0 +int crypto_verify_16(const byte *x,const byte *y); + +/// \brief Compare 32-byte buffers +/// \return 0 on success, non-0 otherwise +/// \sa NaCl crypto_verify documentation +/// \since Crypto++ 6.0 +int crypto_verify_32(const byte *x,const byte *y); + +NAMESPACE_END // CryptoPP +NAMESPACE_END // NaCl + +#endif // CRYPTOPP_DISABLE_NACL +#endif // CRYPTOPP_NACL_H diff --git a/third_party/cryptoppwin/include/cryptopp/nbtheory.h b/third_party/cryptoppwin/include/cryptopp/nbtheory.h new file mode 100644 index 00000000..a494110d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/nbtheory.h @@ -0,0 +1,320 @@ +// nbtheory.h - originally written and placed in the public domain by Wei Dai + +/// \file nbtheory.h +/// \brief Classes and functions for number theoretic operations + +#ifndef CRYPTOPP_NBTHEORY_H +#define CRYPTOPP_NBTHEORY_H + +#include "cryptlib.h" +#include "integer.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief The Small Prime 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 **************** + +/// \brief Generates a provable prime +/// \param rng a RandomNumberGenerator to produce random material +/// \param bits the number of bits in the prime number +/// \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 +/// \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 +/// \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 +/// \return true if p is divisible by some prime less than bound. +/// \details TrialDivision() returns true if p is divisible by some prime less +/// than bound. bound 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 +/// \return true if p is NOT divisible by small primes. +/// \details SmallDivisorsTest() returns true if p is NOT divisible by some +/// prime less than 32719. +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 +/// \return true if the number n is probably prime, false otherwise. +/// \details IsFermatProbablePrime raises b to the n-1 power and checks if +/// the result is congruent to 1 modulo n. +/// \details These is no reason to use IsFermatProbablePrime, use IsStrongProbablePrime or +/// IsStrongLucasProbablePrime instead. +/// \sa IsStrongProbablePrime, IsStrongLucasProbablePrime +CRYPTOPP_DLL bool CRYPTOPP_API IsFermatProbablePrime(const Integer &n, const Integer &b); + +/// \brief Determine if a number is probably prime +/// \param n the number to test +/// \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 +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 +/// \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 +/// \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 +/// \param rng a RandomNumberGenerator to produce random material +/// \param n the number to test +/// \param rounds the number of tests to perform +/// \details This is the Rabin-Miller primality test, i.e. repeating the strong probable prime +/// test for several rounds with random bases +/// \sa Trial divisions before +/// Miller-Rabin checks? on Crypto Stack Exchange +CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng, const Integer &n, unsigned int rounds); + +/// \brief Verifies a number is probably prime +/// \param p a candidate prime to test +/// \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); + +/// \brief Verifies a number is probably prime +/// \param rng a RandomNumberGenerator for randomized testing +/// \param p a candidate prime to test +/// \param level the level of thoroughness of testing +/// \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 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); + +/// \brief Application callback to signal suitability of a cabdidate prime +class CRYPTOPP_DLL PrimeSelector +{ +public: + virtual ~PrimeSelector() {} + const PrimeSelector *GetSelectorPointer() const {return this;} + virtual bool IsAcceptable(const Integer &candidate) const =0; +}; + +/// \brief Finds a random prime of special form +/// \param p an Integer reference to receive the prime +/// \param max the maximum value +/// \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 +/// \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 {x | p<=x<=max and x%mod==equiv} +CRYPTOPP_DLL bool CRYPTOPP_API FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector); + +CRYPTOPP_DLL unsigned int CRYPTOPP_API PrimeSearchInterval(const Integer &max); + +CRYPTOPP_DLL AlgorithmParameters CRYPTOPP_API MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength); + +// ********** other number theoretic functions ************ + +/// \brief Calculate the greatest common divisor +/// \param a the first term +/// \param b the second term +/// \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 +/// \return true if a and b 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 +/// \return the least common multiple of a and b. +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 +/// \return an Integer (a ^ -1) % n or 0 if none exists. +/// \details EuclideanMultiplicativeInverse returns the multiplicative inverse of the Integer +/// *a modulo the Integer b. If no Integer exists then Integer 0 is returned. +inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) + {return a.InverseMod(b);} + + +/// \brief Chinese Remainder Theorem +/// \param xp the first number, mod p +/// \param p the first prime modulus +/// \param xq the second number, mod q +/// \param q the second prime modulus +/// \param u inverse of p mod q +/// \return the CRT value of the parameters +/// \details CRT uses the Chinese Remainder Theorem to calculate x given +/// x mod p and x mod q, and u the inverse of p mod q. +CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u); + +/// \brief Calculate the Jacobi symbol +/// \param a the first term +/// \param b the second term +/// \return the Jacobi symbol. +/// \details Jacobi symbols are calculated using the following rules: +/// -# if b is prime, then Jacobi(a, b), then return 0 +/// -# if a%b==0 AND a is quadratic residue mod b, then return 1 +/// -# return -1 otherwise +/// \details Refer to a number theory book for what Jacobi symbol means when b is not prime. +CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b); + +/// \brief Calculate the Lucas value +/// \return the Lucas value +/// \details Lucas() calculates the Lucas function V_e(p, 1) mod n. +CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n); + +/// \brief Calculate the inverse Lucas value +/// \return the inverse Lucas value +/// \details InverseLucas() calculates x such that m==Lucas(e, x, p*q), +/// p q primes, u is inverse of p mod q. +CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u); + +/// \brief Modular multiplication +/// \param x the first term +/// \param y the second term +/// \param m the modulus +/// \return an Integer (x * y) % m. +inline Integer ModularMultiplication(const Integer &x, const Integer &y, const Integer &m) + {return a_times_b_mod_c(x, y, m);} + +/// \brief Modular exponentiation +/// \param x the base +/// \param e the exponent +/// \param m the modulus +/// \return an Integer (a ^ b) % m. +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 +/// \return the modular square root if it exists +/// \details ModularSquareRoot returns x such that x*x%p == a, p prime +CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p); + +/// \brief Extract a modular root +/// \return a modular root if it exists +/// \details ModularRoot returns x such that a==ModularExponentiation(x, e, p*q), +/// p q primes, and e relatively prime to (p-1)*(q-1), +/// dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1)) +/// and u=inverse of p mod q. +CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u); + +/// \brief Solve a Modular Quadratic Equation +/// \param r1 the first residue +/// \param r2 the second residue +/// \param a the first coefficient +/// \param b the second coefficient +/// \param c the third constant +/// \param p the prime modulus +/// \return true if solutions exist +/// \details SolveModularQuadraticEquation() finds r1 and r2 such that ax^2 + +/// bx + c == 0 (mod p) for x in {r1, r2}, p 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 +/// \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 +/// \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); + +// ******************************************************** + +/// \brief Generator of prime numbers of special forms +class CRYPTOPP_DLL PrimeAndGenerator +{ +public: + /// \brief Construct a PrimeAndGenerator + PrimeAndGenerator() {} + + /// \brief Construct a PrimeAndGenerator + /// \param delta +1 or -1 + /// \param rng a RandomNumberGenerator derived class + /// \param pbits the number of bits in the prime p + /// \details PrimeAndGenerator() generates a random prime p of the form 2*q+delta, where delta is 1 or -1 and q is + /// also prime. Internally the constructor calls Generate(delta, rng, pbits, pbits-1). + /// \pre pbits > 5 + /// \warning This PrimeAndGenerator() is slow because primes of this form are harder to find. + PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits) + {Generate(delta, rng, pbits, pbits-1);} + + /// \brief Construct a PrimeAndGenerator + /// \param delta +1 or -1 + /// \param rng a RandomNumberGenerator derived class + /// \param pbits the number of bits in the prime p + /// \param qbits the number of bits in the prime q + /// \details PrimeAndGenerator() generates a random prime p of the form 2*r*q+delta, where q is also prime. + /// Internally the constructor calls Generate(delta, rng, pbits, qbits). + /// \pre qbits > 4 && pbits > qbits + PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits) + {Generate(delta, rng, pbits, qbits);} + + /// \brief Generate a Prime and Generator + /// \param delta +1 or -1 + /// \param rng a RandomNumberGenerator derived class + /// \param pbits the number of bits in the prime p + /// \param qbits the number of bits in the prime q + /// \details Generate() generates a random prime p of the form 2*r*q+delta, where q is also prime. + void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits); + + /// \brief Retrieve first prime + /// \return Prime() returns the prime p. + const Integer& Prime() const {return p;} + + /// \brief Retrieve second prime + /// \return SubPrime() returns the prime q. + const Integer& SubPrime() const {return q;} + + /// \brief Retrieve the generator + /// \return Generator() returns the generator g. + const Integer& Generator() const {return g;} + +private: + Integer p, q, g; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/nr.h b/third_party/cryptoppwin/include/cryptopp/nr.h new file mode 100644 index 00000000..21558be5 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/nr.h @@ -0,0 +1,11 @@ +// 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 + +#include "gfpcrypt.h" + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/oaep.h b/third_party/cryptoppwin/include/cryptopp/oaep.h new file mode 100644 index 00000000..a709e2ab --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/oaep.h @@ -0,0 +1,54 @@ +// oaep.h - originally written and placed in the public domain by Wei Dai + +/// \file oaep.h +/// \brief Classes for optimal asymmetric encryption padding +/// \since Crypto++ 2.1 + +#ifndef CRYPTOPP_OAEP_H +#define CRYPTOPP_OAEP_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief OAEP padding base class +/// \since Crypto++ 2.1 +class CRYPTOPP_DLL OAEP_Base : public PK_EncryptionMessageEncodingMethod +{ +public: + bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} + size_t MaxUnpaddedLength(size_t paddedLength) const; + void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs ¶meters) const; + DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; + +protected: + virtual unsigned int DigestSize() const =0; + virtual HashTransformation * NewHash() const =0; + virtual MaskGeneratingFunction * NewMGF() const =0; +}; + +/// \brief OAEP padding +/// \tparam H HashTransformation derived class +/// \tparam MGF MaskGeneratingFunction derived class +/// \sa EME-OAEP, for use with classes derived from TF_ES +/// \since Crypto++ 2.1 +template +class OAEP : public OAEP_Base, public EncryptionStandard +{ +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} + typedef OAEP EncryptionMessageEncodingMethod; + +protected: + unsigned int DigestSize() const {return H::DIGESTSIZE;} + HashTransformation * NewHash() const {return new H;} + MaskGeneratingFunction * NewMGF() const {return new MGF;} +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS OAEP; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/oids.h b/third_party/cryptoppwin/include/cryptopp/oids.h new file mode 100644 index 00000000..936f68b2 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/oids.h @@ -0,0 +1,197 @@ +// oids.h - originally written and placed in the public domain by Wei Dai + +/// \file oids.h +/// \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. +/// There seems to be some confusion between the text of GmSSL's oid.html web page +/// and the actual OID used in the code. We used the same OIDs that were detailed in +/// http://github.com/guanzhi/GmSSL/blob/master/crypto/objects/objects.txt. + +#ifndef CRYPTOPP_OIDS_H +#define CRYPTOPP_OIDS_H + +#include "asn.h" + +NAMESPACE_BEGIN(CryptoPP) + +NAMESPACE_BEGIN(ASN1) + +#define DEFINE_OID(value, name) inline OID name() {return value;} + +DEFINE_OID(1, iso) + DEFINE_OID(iso()+2, member_body) + DEFINE_OID(member_body()+156, iso_cn) + DEFINE_OID(iso_cn()+10197, oscca) + DEFINE_OID(oscca()+1, sm_scheme) + DEFINE_OID(sm_scheme()+104, sms4) + DEFINE_OID(sm_scheme()+301, sm2p256v1) + DEFINE_OID(sm2p256v1()+1, sm2sign) + DEFINE_OID(sm2p256v1()+2, sm2exchange) + DEFINE_OID(sm2p256v1()+3, sm2encrypt) + DEFINE_OID(sm2encrypt()+1, sm2encrypt_recommendedParameters) + 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, 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) + DEFINE_OID(id_fieldType()+2, characteristic_two_field) + DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis) + DEFINE_OID(id_characteristic_two_basis()+1, gnBasis) + DEFINE_OID(id_characteristic_two_basis()+2, tpBasis) + DEFINE_OID(id_characteristic_two_basis()+3, ppBasis) + DEFINE_OID(ansi_x9_62()+2, id_publicKeyType) + 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) + // 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) + DEFINE_OID(internet_private()+1, enterprise) + DEFINE_OID(enterprise()+11591,gnu) + DEFINE_OID(gnu()+15,ellipticCurve) + DEFINE_OID(ellipticCurve()+1,curve25519) + DEFINE_OID(ellipticCurve()+2,curve448) + DEFINE_OID(ellipticCurve()+3,curve25519ph) + DEFINE_OID(ellipticCurve()+4,curve448ph) + DEFINE_OID(identified_organization()+14, oiw) + 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) + DEFINE_OID(teletrust_algorithm()+3+2+8+1, teletrust_ellipticCurve) + DEFINE_OID(teletrust_ellipticCurve()+1+1, brainpoolP160r1) + DEFINE_OID(teletrust_ellipticCurve()+1+3, brainpoolP192r1) + DEFINE_OID(teletrust_ellipticCurve()+1+5, brainpoolP224r1) + DEFINE_OID(teletrust_ellipticCurve()+1+7, brainpoolP256r1) + 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 + // first curves based on GF(p) + DEFINE_OID(certicom_ellipticCurve()+6, secp112r1) + DEFINE_OID(certicom_ellipticCurve()+7, secp112r2) + DEFINE_OID(certicom_ellipticCurve()+8, secp160r1) + DEFINE_OID(certicom_ellipticCurve()+9, secp160k1) + DEFINE_OID(certicom_ellipticCurve()+10, secp256k1) + DEFINE_OID(certicom_ellipticCurve()+28, secp128r1) + DEFINE_OID(certicom_ellipticCurve()+29, secp128r2) + DEFINE_OID(certicom_ellipticCurve()+30, secp160r2) + DEFINE_OID(certicom_ellipticCurve()+31, secp192k1) + DEFINE_OID(certicom_ellipticCurve()+32, secp224k1) + DEFINE_OID(certicom_ellipticCurve()+33, secp224r1) + DEFINE_OID(certicom_ellipticCurve()+34, secp384r1) + DEFINE_OID(certicom_ellipticCurve()+35, secp521r1) + // then curves based on GF(2^n) + DEFINE_OID(certicom_ellipticCurve()+1, sect163k1) + DEFINE_OID(certicom_ellipticCurve()+2, sect163r1) + DEFINE_OID(certicom_ellipticCurve()+3, sect239k1) + DEFINE_OID(certicom_ellipticCurve()+4, sect113r1) + DEFINE_OID(certicom_ellipticCurve()+5, sect113r2) + DEFINE_OID(certicom_ellipticCurve()+15, sect163r2) + DEFINE_OID(certicom_ellipticCurve()+16, sect283k1) + DEFINE_OID(certicom_ellipticCurve()+17, sect283r1) + DEFINE_OID(certicom_ellipticCurve()+22, sect131r1) + DEFINE_OID(certicom_ellipticCurve()+23, sect131r2) + DEFINE_OID(certicom_ellipticCurve()+24, sect193r1) + DEFINE_OID(certicom_ellipticCurve()+25, sect193r2) + DEFINE_OID(certicom_ellipticCurve()+26, sect233k1) + DEFINE_OID(certicom_ellipticCurve()+27, sect233r1) + DEFINE_OID(certicom_ellipticCurve()+36, sect409k1) + DEFINE_OID(certicom_ellipticCurve()+37, sect409r1) + DEFINE_OID(certicom_ellipticCurve()+38, sect571k1) + DEFINE_OID(certicom_ellipticCurve()+39, sect571r1) +DEFINE_OID(2, joint_iso_ccitt) + DEFINE_OID(joint_iso_ccitt()+16, country) + DEFINE_OID(country()+840, joint_iso_ccitt_us) + DEFINE_OID(joint_iso_ccitt_us()+1, us_organization) + DEFINE_OID(us_organization()+101, us_gov) + DEFINE_OID(us_gov()+3, csor) + DEFINE_OID(csor()+4, nistalgorithms) + DEFINE_OID(nistalgorithms()+1, aes) + DEFINE_OID(aes()+1, id_aes128_ECB) + DEFINE_OID(aes()+2, id_aes128_cbc) + DEFINE_OID(aes()+3, id_aes128_ofb) + DEFINE_OID(aes()+4, id_aes128_cfb) + DEFINE_OID(aes()+21, id_aes192_ECB) + DEFINE_OID(aes()+22, id_aes192_cbc) + DEFINE_OID(aes()+23, id_aes192_ofb) + DEFINE_OID(aes()+24, id_aes192_cfb) + DEFINE_OID(aes()+41, id_aes256_ECB) + DEFINE_OID(aes()+42, id_aes256_cbc) + DEFINE_OID(aes()+43, id_aes256_ofb) + DEFINE_OID(aes()+44, id_aes256_cfb) + DEFINE_OID(nistalgorithms()+2, nist_hashalgs) + DEFINE_OID(nist_hashalgs()+1, id_sha256) + DEFINE_OID(nist_hashalgs()+2, id_sha384) + DEFINE_OID(nist_hashalgs()+3, id_sha512) + DEFINE_OID(nist_hashalgs()+4, id_sha224) + DEFINE_OID(nist_hashalgs()+7, id_sha3_224) + 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 + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/osrng.h b/third_party/cryptoppwin/include/cryptopp/osrng.h new file mode 100644 index 00000000..31c32957 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/osrng.h @@ -0,0 +1,304 @@ +// osrng.h - originally written and placed in the public domain by Wei Dai + +/// \file osrng.h +/// \brief Classes for access to the operating system's random number generators + +#ifndef CRYPTOPP_OSRNG_H +#define CRYPTOPP_OSRNG_H + +#include "config.h" + +#if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE) + +#include "cryptlib.h" +#include "randpool.h" +#include "smartptr.h" +#include "fips140.h" +#include "hkdf.h" +#include "rng.h" +#include "aes.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Exception thrown when an operating system error is encountered +class CRYPTOPP_DLL OS_RNG_Err : public Exception +{ +public: + /// \brief Constructs an OS_RNG_Err + /// \param operation the operation or API call when the error occurs + OS_RNG_Err(const std::string &operation); +}; + +#ifdef NONBLOCKING_RNG_AVAILABLE + +#ifdef CRYPTOPP_WIN32_AVAILABLE +/// \brief Wrapper for Microsoft crypto service provider +/// \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI +class CRYPTOPP_DLL MicrosoftCryptoProvider +{ +public: + /// \brief Construct a MicrosoftCryptoProvider + MicrosoftCryptoProvider(); + ~MicrosoftCryptoProvider(); + +// type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include +#if defined(USE_MS_CRYPTOAPI) +# if defined(__CYGWIN__) && defined(__x86_64__) + typedef unsigned long long ProviderHandle; +# elif defined(WIN64) || defined(_WIN64) + typedef unsigned __int64 ProviderHandle; +# else + typedef unsigned long ProviderHandle; +# endif +#elif defined(USE_MS_CNGAPI) + typedef void *PVOID; + typedef PVOID ProviderHandle; +#endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI + + /// \brief Retrieves the 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. + ProviderHandle GetProviderHandle() const {return m_hProvider;} + +private: + ProviderHandle m_hProvider; +}; + +#if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CRYPTOAPI) +# pragma comment(lib, "advapi32.lib") +#endif + +#if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CNGAPI) +# pragma comment(lib, "bcrypt.lib") +#endif + +#endif // CRYPTOPP_WIN32_AVAILABLE + +/// \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. +class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "NonblockingRng"; } + + ~NonblockingRng(); + + /// \brief Construct a NonblockingRng + NonblockingRng(); + + /// \brief Generate random array of bytes + /// \param output the byte buffer + /// \param size the length of the buffer, in bytes + /// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock(). + void GenerateBlock(byte *output, size_t size); + +protected: +#ifdef CRYPTOPP_WIN32_AVAILABLE + MicrosoftCryptoProvider m_Provider; +#else + int m_fd; +#endif +}; + +#endif + +#if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) + +/// \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 [RFC PATCH v12 3/4] Linux Random +/// Number Generator on the kernel-crypto mailing list. +class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "BlockingRng"; } + + ~BlockingRng(); + + /// \brief Construct a BlockingRng + BlockingRng(); + + /// \brief Generate random array of bytes + /// \param output the byte buffer + /// \param size the length of the buffer, in bytes + /// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock(). + void GenerateBlock(byte *output, size_t size); + +protected: + int m_fd; +}; + +#endif + +/// OS_GenerateRandomBlock +/// \brief Generate random array of bytes +/// \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. +/// \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 +/// 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. +/// \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: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "AutoSeededRandomPool"; } + + ~AutoSeededRandomPool() {} + + /// \brief Construct an AutoSeededRandomPool + /// \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. + explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) + {Reseed(blocking, seedSize);} + + /// \brief Reseed an AutoSeededRandomPool + /// \param blocking controls seeding with BlockingRng or NonblockingRng + /// \param seedSize the size of the seed, in bytes + void Reseed(bool blocking = false, unsigned int seedSize = 32); +}; + +/// \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. +/// \details You should reseed the generator after a fork() to avoid multiple generators +/// with the same internal state. +/// \sa X917RNG, DefaultAutoSeededRNG +template +class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable +{ +public: + static std::string StaticAlgorithmName() { + return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")"); + } + + ~AutoSeededX917RNG() {} + + /// \brief Construct an AutoSeededX917RNG + /// \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. + /// \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 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 *input = NULLPTR, size_t length = 0); + + /// \brief Deterministically reseed an AutoSeededX917RNG for testing + /// \param key the key to use for the deterministic reseeding + /// \param keylength the size of the key, in bytes + /// \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. + void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector); + + bool CanIncorporateEntropy() const {return true;} + void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) + {m_rng->GenerateIntoBufferedTransformation(target, channel, length);} + + std::string AlgorithmProvider() const; + +private: + member_ptr m_rng; +}; + +template +void AutoSeededX917RNG::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) +{ + m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); +} + +template +void AutoSeededX917RNG::Reseed(bool blocking, const byte *input, size_t length) +{ + 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, temp, temp.size()); + + HKDF 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 (std::memcmp(key, seed, STDMIN((size_t)BlockSize, (size_t)KeyLength)) == 0); + + Reseed(key, KeyLength, seed, NULLPTR); +} + +template +std::string AutoSeededX917RNG::AlgorithmProvider() const +{ + // Hack for now... We need to instantiate one + typename BLOCK_CIPHER::Encryption bc; + return bc.AlgorithmProvider(); +} + +CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG; + +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) +/// \brief A typedef providing a default generator +/// \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG or AutoSeededRandomPool. +/// If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is +/// AutoSeededX917RNG. 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 in FIPS mode, otherwise it's AutoSeededRandomPool +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +typedef AutoSeededX917RNG DefaultAutoSeededRNG; +#else +typedef AutoSeededRandomPool DefaultAutoSeededRNG; +#endif +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +NAMESPACE_END + +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ossig.h b/third_party/cryptoppwin/include/cryptopp/ossig.h new file mode 100644 index 00000000..ce23b73d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ossig.h @@ -0,0 +1,128 @@ +// ossig.h - written and placed in the public domain by Jeffrey Walton +// +/// \file ossig.h +/// \brief Utility class for trapping OS signals. +/// \since Crypto++ 5.6.5 + +#ifndef CRYPTOPP_OS_SIGNAL_H +#define CRYPTOPP_OS_SIGNAL_H + +#include "config.h" + +#if defined(UNIX_SIGNALS_AVAILABLE) +# include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** Unix and Linux compatibles *************** + +#if defined(UNIX_SIGNALS_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) + +/// \brief Signal handler function pointer +/// \details SignalHandlerFn is provided as a stand alone function pointer with external "C" linkage +/// \sa SignalHandler, NullSignalHandler +extern "C" { + typedef void (*SignalHandlerFn) (int); +} + +/// \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 member function's implicit +/// external "C++" linkage. +/// \sa SignalHandler, SignalHandlerFn +extern "C" { + inline void NullSignalHandler(int unused) {CRYPTOPP_UNUSED(unused);} +} + +/// Signal handler for Linux and Unix compatibles +/// \tparam S Signal number +/// \tparam O Flag indicating if an existing handler should be overwritten +/// \details SignalHandler() can be used to install a signal handler with the signature +/// void handler_fn(int). If SignalHandlerFn is not NULL, then +/// the sigaction is set to the function and the sigaction flags is set to the flags. +/// If SignalHandlerFn is NULL, 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. +/// \details On Cygwin systems using Newlib, you should define _XOPEN_SOURCE=700 or +/// _GNU_SOURCE; or use -std=gnu++03, -std=gnu++11, or similar. If +/// you compile with -std=c++03, -std=c++11 or similar, then define +/// _XOPEN_SOURCE=700. +/// \warning Do not use SignalHandler in a code block that uses setjmp or longjmp +/// because the destructor may not run. +/// \since Crypto++ 5.6.5 +/// \sa NullSignalHandler, SignalHandlerFn, \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", DebugTrapHandler +template +struct SignalHandler +{ + /// \brief Construct a signal handler + /// \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 + /// void handler_fn(int). If SignalHandlerFn is not NULL, then + /// the sigaction is set to the function and the sigaction flags is set to the flags. + /// If SignalHandlerFn is NULL, 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. + /// \details On Cygwin systems using Newlib, you should define _XOPEN_SOURCE=700 or + /// _GNU_SOURCE; or use -std=gnu++03, -std=gnu++11, or similar. If + /// you compile with -std=c++03, -std=c++11 or similar, then define + /// _XOPEN_SOURCE=700. + /// \warning Do not use SignalHandler in a code block that uses setjmp or longjmp + /// because the destructor may not run. setjmp 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) + { + // http://pubs.opengroup.org/onlinepubs/007908799/xsh/sigaction.html + struct sigaction new_handler; + + do + { + int ret = 0; + + ret = sigaction (S, 0, &m_old); + if (ret != 0) break; // Failed + + // Don't step on another's handler if Overwrite=false + if (m_old.sa_handler != 0 && !O) break; + + // Cygwin/Newlib requires -D_XOPEN_SOURCE=700 + ret = sigemptyset (&new_handler.sa_mask); + if (ret != 0) break; // Failed + + new_handler.sa_handler = (pfn ? pfn : &NullSignalHandler); + new_handler.sa_flags = (pfn ? flags : 0); + + // Install it + ret = sigaction (S, &new_handler, 0); + if (ret != 0) break; // Failed + + m_installed = true; + + } while(0); + } + + ~SignalHandler() + { + if (m_installed) + sigaction (S, &m_old, 0); + } + +private: + struct sigaction m_old; + bool m_installed; + +private: + // Not copyable + SignalHandler(const SignalHandler &); + void operator=(const SignalHandler &); +}; +#endif + +NAMESPACE_END + +#endif // CRYPTOPP_OS_SIGNAL_H diff --git a/third_party/cryptoppwin/include/cryptopp/padlkrng.h b/third_party/cryptoppwin/include/cryptopp/padlkrng.h new file mode 100644 index 00000000..7c6b0b33 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/padlkrng.h @@ -0,0 +1,138 @@ +// via-rng.h - written and placed in public domain by Jeffrey Walton + +/// \file padlkrng.h +/// \brief Classes for VIA Padlock RNG +/// \since Crypto++ 6.0 +/// \sa VIA +/// Padlock on the Crypto++ wiki + +#ifndef CRYPTOPP_PADLOCK_RNG_H +#define CRYPTOPP_PADLOCK_RNG_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Exception thrown when a PadlockRNG generator encounters +/// a generator related error. +/// \since Crypto++ 6.0 +class PadlockRNG_Err : public Exception +{ +public: + PadlockRNG_Err(const std::string &operation) + : Exception(OTHER_ERROR, "PadlockRNG: " + operation + " operation failed") {} + PadlockRNG_Err(const std::string &component, const std::string &message) + : Exception(OTHER_ERROR, component + ": " + message) {} +}; + +/// \brief Hardware generated random numbers using VIA XSTORE +/// \details Some VIA processors provide a Security Engine called Padlock. The Padlock +/// Security Engine provides AES, SHA and a RNG. The PadlockRNG class provides access +/// to the RNG. +/// \details The VIA generator uses an 8 byte FIFO buffer for random numbers. The +/// generator can be configured to discard bits from the buffer to resist analysis. +/// The divisor controls the number of bytes discarded. The formula for +/// the discard amount is 2**divisor - 1. When divisor=0 no bits +/// are discarded and the entire 8 byte buffer is read. If divisor=3 then +/// 7 bytes are discarded and 1 byte is read. TheVIA SDK samples use divisor=1. +/// \details Cryptography Research, Inc (CRI) audited the Padlock Security Engine +/// in 2003. CRI provided recommendations to operate the generator for secure and +/// non-secure applications. Additionally, the Programmers Guide and SDK provided a +/// different configuration in the sample code. +/// \details You can operate the generator according to CRI recommendations by setting +/// divisor, reading one word (or partial word) at a time from the FIFO, and +/// then inspecting the MSR after each read. +/// \details The audit report with recommendations is available on the Crypto++ wiki +/// at VIA Padlock. +/// \sa MaurerRandomnessTest() for random bit generators +/// \since Crypto++ 6.0 +class PadlockRNG : public RandomNumberGenerator +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "PadlockRNG"; } + + virtual ~PadlockRNG() {} + + /// \brief Construct a PadlockRNG generator + /// \param divisor the XSTORE divisor + /// \details Some VIA processors provide a Security Engine called Padlock. The Padlock + /// Security Engine provides AES, SHA and a RNG. The PadlockRNG class provides access + /// to the RNG. + /// \details The VIA generator uses an 8 byte FIFO buffer for random numbers. The + /// generator can be configured to discard bits from the buffer to resist analysis. + /// The divisor controls the number of bytes discarded. The formula for + /// the discard amount is 2**divisor - 1. When divisor=0 no bits + /// are discarded and the entire 8 byte buffer is read. If divisor=3 then + /// 7 bytes are discarded and 1 byte is read. VIA SDK samples use divisor=1. + /// \details Cryptography Research, Inc (CRI) audited the Padlock Security Engine + /// in 2003. CRI provided recommendations to operate the generator for secure and + /// non-secure applications. Additionally, the Programmers SDK provided a different + /// configuration in the sample code. + /// \details The audit report with recommendations is available on the Crypto++ wiki + /// at VIA Padlock. + /// \sa SetDivisor, GetDivisor + PadlockRNG(word32 divisor=1); + + /// \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 Padlock generator discards words, not bytes. If n is + /// not a multiple of a 32-bit 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; + + /// \brief Set the XSTORE divisor + /// \param divisor the XSTORE divisor + /// \return the old XSTORE divisor + word32 SetDivisor(word32 divisor) + { + word32 old = m_divisor; + m_divisor = DivisorHelper(divisor); + return old; + } + + /// \brief Get the XSTORE divisor + /// \return the current XSTORE divisor + word32 GetDivisor() const + { + return m_divisor; + } + + /// \brief Get the MSR for the last operation + /// \return the MSR for the last read operation + word32 GetMSR() const + { + return m_msr; + } + +protected: + inline word32 DivisorHelper(word32 divisor) + { + return divisor > 3 ? 3 : divisor; + } + +private: + FixedSizeAlignedSecBlock m_buffer; + word32 m_divisor, m_msr; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_PADLOCK_RNG_H diff --git a/third_party/cryptoppwin/include/cryptopp/panama.h b/third_party/cryptoppwin/include/cryptopp/panama.h new file mode 100644 index 00000000..9c10f82c --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/panama.h @@ -0,0 +1,169 @@ +// panama.h - originally written and placed in the public domain by Wei Dai + +/// \file panama.h +/// \brief Classes for Panama hash and stream cipher + +#ifndef CRYPTOPP_PANAMA_H +#define CRYPTOPP_PANAMA_H + +#include "strciphr.h" +#include "iterhash.h" +#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_MIXED_ASM) +//# define CRYPTOPP_DISABLE_PANAMA_ASM +//#endif + +// https://github.com/weidai11/cryptopp/issues/758 +#define CRYPTOPP_DISABLE_PANAMA_ASM 1 + +NAMESPACE_BEGIN(CryptoPP) + +// Base class, do not use directly +template +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); + + FixedSizeAlignedSecBlock m_state; +}; + +namespace Weak { +/// \brief Panama hash +/// \sa Panama Hash +template +class PanamaHash : protected Panama, public AlgorithmImpl, PanamaHash > +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE = 32); + virtual ~PanamaHash() {} + PanamaHash() {Panama::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::AlgorithmProvider();} // Fix https://github.com/weidai11/cryptopp/issues/801 + +protected: + void Init() {Panama::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 m_buf; +}; +} + +/// \brief MAC construction using a hermetic hash function +template +class HermeticHashFunctionMAC : public AlgorithmImpl > >, T_Info> +{ +public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) + { + CRYPTOPP_UNUSED(params); + + m_key.Assign(key, length); + Restart(); + } + + void Restart() + { + m_hash.Restart(); + m_keyed = false; + } + + void Update(const byte *input, size_t length) + { + if (!m_keyed) + KeyHash(); + m_hash.Update(input, length); + } + + void TruncatedFinal(byte *digest, size_t digestSize) + { + if (!m_keyed) + KeyHash(); + m_hash.TruncatedFinal(digest, digestSize); + m_keyed = false; + } + + unsigned int DigestSize() const + {return m_hash.DigestSize();} + unsigned int BlockSize() const + {return m_hash.BlockSize();} + unsigned int OptimalBlockSize() const + {return m_hash.OptimalBlockSize();} + unsigned int OptimalDataAlignment() const + {return m_hash.OptimalDataAlignment();} + +protected: + void KeyHash() + { + m_hash.Update(m_key, m_key.size()); + m_keyed = true; + } + + T_Hash m_hash; + bool m_keyed; + SecByteBlock m_key; +}; + +namespace Weak { +/// \brief Panama message authentication code +template +class PanamaMAC : public HermeticHashFunctionMAC > +{ +public: + PanamaMAC() {} + PanamaMAC(const byte *key, unsigned int length) + {this->SetKey(key, length);} +}; +} + +/// \brief Panama stream cipher information +template +struct PanamaCipherInfo : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 32> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == BIG_ENDIAN_ORDER ? "Panama-BE" : "Panama-LE";} +}; + +/// \brief Panama stream cipher operation +template +class PanamaCipherPolicy : public AdditiveCipherConcretePolicy, + public PanamaCipherInfo, + protected Panama +{ +protected: + virtual ~PanamaCipherPolicy() {} + std::string AlgorithmProvider() const; + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + bool CipherIsRandomAccess() const {return false;} + void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); + unsigned int GetAlignment() const; + + FixedSizeSecBlock m_key; + FixedSizeSecBlock m_buf; +}; + +/// \brief Panama stream cipher +/// \sa Panama Stream Cipher +template +struct PanamaCipher : public PanamaCipherInfo, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, PanamaCipherInfo > Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/pch.h b/third_party/cryptoppwin/include/cryptopp/pch.h new file mode 100644 index 00000000..2cd163ea --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/pch.h @@ -0,0 +1,31 @@ +// pch.h - originally written and placed in the public domain by Wei Dai + +/// \file pch.h +/// \brief Precompiled header file +/// \details The precompiled header files are used Windows. + +#ifndef CRYPTOPP_PCH_H +#define CRYPTOPP_PCH_H + +# ifdef CRYPTOPP_GENERATE_X64_MASM + #include "cpu.h" + +# else + #include "config.h" + + #ifdef USE_PRECOMPILED_HEADERS + #include "simple.h" + #include "secblock.h" + #include "misc.h" + #include "smartptr.h" + #include "stdcpp.h" + #endif +# endif + +// Enable file and line numbers, if available. +// #if defined(_MSC_VER) && defined(_DEBUG) && defined(USE_PRECOMPILED_HEADERS) +// # define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) +// # define new DEBUG_NEW +// #endif + +#endif // CRYPTOPP_PCH_H diff --git a/third_party/cryptoppwin/include/cryptopp/pkcspad.h b/third_party/cryptoppwin/include/cryptopp/pkcspad.h new file mode 100644 index 00000000..f112c521 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/pkcspad.h @@ -0,0 +1,123 @@ +// pkcspad.h - originally written and placed in the public domain by Wei Dai + +/// \file pkcspad.h +/// \brief Classes for PKCS padding schemes +/// \details PKCS #1 v1.5, v2.0 and P1363a allow MD2, MD5, SHA1, SHA224, SHA256, SHA384, +/// SHA512, Tiger and RipeMd-160 to be instantiated. + +#ifndef CRYPTOPP_PKCSPAD_H +#define CRYPTOPP_PKCSPAD_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "hashfwd.h" + +#ifdef CRYPTOPP_IS_DLL +#include "sha.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief PKCS #1 v1.5 Encryption Padding Scheme +/// \sa EME-PKCS1-v1_5 +class PKCS_EncryptionPaddingScheme : public PK_EncryptionMessageEncodingMethod +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "EME-PKCS1-v1_5";} + + size_t MaxUnpaddedLength(size_t paddedLength) const; + void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs ¶meters) const; + DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; +}; + +/// \brief PKCS #1 decoration data structure +template class PKCS_DigestDecoration +{ +public: + static const byte decoration[]; + static const unsigned int length; +}; + +// PKCS_DigestDecoration can be instantiated with the following +// classes as specified in PKCS #1 v2.0 and P1363a +// SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, RIPEMD160, MD2, MD5 + +#if defined(CRYPTOPP_IS_DLL) +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +// http://github.com/weidai11/cryptopp/issues/517 +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +#endif + +// https://github.com/weidai11/cryptopp/issues/300 and +// https://github.com/weidai11/cryptopp/issues/533 +#if defined(__clang__) +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; + +// http://github.com/weidai11/cryptopp/issues/517 +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; + +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +template<> const byte PKCS_DigestDecoration::decoration[]; +template<> const unsigned int PKCS_DigestDecoration::length; +#endif + +/// \brief PKCS #1 v1.5 Signature Encoding Scheme +/// \sa EMSA-PKCS1-v1_5 +class CRYPTOPP_DLL PKCS1v15_SignatureMessageEncodingMethod : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "EMSA-PKCS1-v1_5";} + + size_t MinRepresentativeBitLength(size_t hashIdentifierSize, size_t digestSize) const + {return 8 * (digestSize + hashIdentifierSize + 10);} + + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; + + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier Lookup() + { + return HashIdentifier(PKCS_DigestDecoration::decoration, PKCS_DigestDecoration::length); + } + }; + }; +}; + +/// \brief PKCS #1 version 1.5, for use with RSAES and RSASS +/// \dontinclude pkcspad.h + +struct PKCS1v15 : public SignatureStandard, public EncryptionStandard +{ + typedef PKCS_EncryptionPaddingScheme EncryptionMessageEncodingMethod; + typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/poly1305.h b/third_party/cryptoppwin/include/cryptopp/poly1305.h new file mode 100644 index 00000000..19e712bd --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/poly1305.h @@ -0,0 +1,241 @@ +// 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 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 Crypto++ also supplies the IETF's version of Poly1305. It is a slightly different +/// algorithm than Bernstein's version. +/// \sa Daniel J. Bernstein The Poly1305-AES +/// Message-Authentication Code (20050329), RFC +/// 8439, ChaCha20 and Poly1305 for IETF Protocols and Andy Polyakov Poly1305 Revised +/// \since Poly1305 since Crypto++ 6.0, Poly1305TLS since Crypto++ 8.1 + +#ifndef CRYPTOPP_POLY1305_H +#define CRYPTOPP_POLY1305_H + +#include "cryptlib.h" +#include "seckey.h" +#include "secblock.h" +#include "argnames.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +////////////////////////////// Bernstein Poly1305 ////////////////////////////// + +/// \brief Poly1305 message authentication code base class +/// \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 CRYPTOPP_NO_VTABLE Poly1305_Base : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 16>, public MessageAuthenticationCode +{ + CRYPTOPP_COMPILE_ASSERT(T::DEFAULT_KEYLENGTH == 16); + CRYPTOPP_COMPILE_ASSERT(T::BLOCKSIZE == 16); + +public: + static std::string StaticAlgorithmName() {return std::string("Poly1305(") + T::StaticAlgorithmName() + ")";} + + 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); + void GetNextIV (RandomNumberGenerator &rng, byte *iv); + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + 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;} + + 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); + + typename T::Encryption m_cipher; + + // Accumulated hash, clamped r-key, and encrypted nonce + FixedSizeAlignedSecBlock m_h; + FixedSizeAlignedSecBlock m_r; + FixedSizeAlignedSecBlock m_n; + + // Accumulated message bytes and index + FixedSizeAlignedSecBlock m_acc, m_nk; + size_t m_idx; + + // Track nonce reuse; assert in debug but continue + bool m_used; +}; + +/// \brief Poly1305 message authentication code +/// \tparam T class derived from BlockCipherDocumentation with 16-byte key and 16-byte blocksize +/// \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 The key is 32 bytes and a concatenation key = {k,s}, where +/// k is the AES key and r 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 each time its needed. +///
  SecByteBlock key(32), nonce(16);
+///   prng.GenerateBlock(key, key.size());
+///   prng.GenerateBlock(nonce, nonce.size());
+///
+///   Poly1305 poly1305(key, key.size(), nonce, nonce.size());
+///   poly1305.Update(...);
+///   poly1305.Final(...);
+/// +/// \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 using GetNextIV(). +///
  SecByteBlock key(32), nonce(16);
+///   prng.GenerateBlock(key, key.size());
+///   prng.GenerateBlock(nonce, nonce.size());
+///
+///   // First message
+///   Poly1305 poly1305(key, key.size());
+///   poly1305.Resynchronize(nonce);
+///   poly1305.Update(...);
+///   poly1305.Final(...);
+///
+///   // Second message
+///   poly1305.GetNextIV(prng, nonce);
+///   poly1305.Resynchronize(nonce);
+///   poly1305.Update(...);
+///   poly1305.Final(...);
+///   ...
+/// \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 The Poly1305-AES +/// Message-Authentication Code (20050329) and Andy Polyakov Poly1305 Revised +/// \since Crypto++ 6.0 +template +class Poly1305 : public MessageAuthenticationCodeFinal > +{ +public: + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=Poly1305_Base::DEFAULT_KEYLENGTH); + + /// \brief Construct a Poly1305 + Poly1305() {} + + /// \brief Construct a Poly1305 + /// \param key a byte array used to key the cipher + /// \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 The key is 32 bytes and a concatenation key = {k,s}, where + /// k is the AES key and r 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 ¶ms); + 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 m_h; + FixedSizeAlignedSecBlock m_r; + FixedSizeAlignedSecBlock m_n; + + // Accumulated message bytes and index + FixedSizeAlignedSecBlock 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 +/// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, and +/// TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. +/// \details The key is 32 bytes and a concatenation key = {r,s}, where +/// r is additional key that gets clamped and s 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. +///
  SecByteBlock key(32);
+///   prng.GenerateBlock(key, key.size());
+///
+///   Poly1305TLS poly1305(key, key.size());
+///   poly1305.Update(...);
+///   poly1305.Final(...);
+/// +/// \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. +///
  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(...);
+///   ...
+/// \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(), RFC +/// 8439, ChaCha20 and Poly1305 for IETF Protocols +DOCUMENTED_TYPEDEF(MessageAuthenticationCodeFinal, Poly1305TLS); + +NAMESPACE_END + +#endif // CRYPTOPP_POLY1305_H diff --git a/third_party/cryptoppwin/include/cryptopp/polynomi.h b/third_party/cryptoppwin/include/cryptopp/polynomi.h new file mode 100644 index 00000000..9a754ef3 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/polynomi.h @@ -0,0 +1,463 @@ +// polynomi.h - originally written and placed in the public domain by Wei Dai + +/// \file polynomi.h +/// \brief Classes for polynomial basis and operations + +#ifndef CRYPTOPP_POLYNOMI_H +#define CRYPTOPP_POLYNOMI_H + +#include "cryptlib.h" +#include "secblock.h" +#include "algebra.h" +#include "misc.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// represents single-variable polynomials over arbitrary rings +/*! \nosubgrouping */ +template class PolynomialOver +{ +public: + /// \name ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + /// division by zero exception + class DivideByZero : public Exception + { + public: + DivideByZero() : Exception(OTHER_ERROR, "PolynomialOver: division by zero") {} + }; + + /// specify the distribution for randomization functions + class RandomizationParameter + { + public: + RandomizationParameter(unsigned int coefficientCount, const typename T::RandomizationParameter &coefficientParameter ) + : m_coefficientCount(coefficientCount), m_coefficientParameter(coefficientParameter) {} + + private: + unsigned int m_coefficientCount; + typename T::RandomizationParameter m_coefficientParameter; + friend class PolynomialOver; + }; + + typedef T Ring; + typedef typename T::Element CoefficientType; + //@} + + /// \name CREATORS + //@{ + /// creates the zero polynomial + PolynomialOver() {} + + /// + PolynomialOver(const Ring &ring, unsigned int count) + : m_coefficients((size_t)count, ring.Identity()) {} + + /// copy constructor + PolynomialOver(const PolynomialOver &t) + : m_coefficients(t.m_coefficients.size()) {*this = t;} + + /// construct constant polynomial + PolynomialOver(const CoefficientType &element) + : m_coefficients(1, element) {} + + /// construct polynomial with specified coefficients, starting from coefficient of x^0 + template PolynomialOver(Iterator begin, Iterator end) + : m_coefficients(begin, end) {} + + /// convert from string + PolynomialOver(const char *str, const Ring &ring) {FromStr(str, ring);} + + /// convert from big-endian byte array + PolynomialOver(const byte *encodedPolynomialOver, unsigned int byteCount); + + /// convert from Basic Encoding Rules encoded byte array + explicit PolynomialOver(const byte *BEREncodedPolynomialOver); + + /// convert from BER encoded byte array stored in a BufferedTransformation object + explicit PolynomialOver(BufferedTransformation &bt); + + /// create a random PolynomialOver + PolynomialOver(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring) + {Randomize(rng, parameter, ring);} + //@} + + /// \name ACCESSORS + //@{ + /// the zero polynomial will return a degree of -1 + int Degree(const Ring &ring) const {return int(CoefficientCount(ring))-1;} + /// + unsigned int CoefficientCount(const Ring &ring) const; + /// return coefficient for x^i + CoefficientType GetCoefficient(unsigned int i, const Ring &ring) const; + //@} + + /// \name MANIPULATORS + //@{ + /// + PolynomialOver& operator=(const PolynomialOver& t); + + /// + void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring); + + /// set the coefficient for x^i to value + void SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring); + + /// + void Negate(const Ring &ring); + + /// + void swap(PolynomialOver &t); + //@} + + + /// \name BASIC ARITHMETIC ON POLYNOMIALS + //@{ + bool Equals(const PolynomialOver &t, const Ring &ring) const; + bool IsZero(const Ring &ring) const {return CoefficientCount(ring)==0;} + + PolynomialOver Plus(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver Minus(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver Inverse(const Ring &ring) const; + + PolynomialOver Times(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver DividedBy(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver Modulo(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver MultiplicativeInverse(const Ring &ring) const; + bool IsUnit(const Ring &ring) const; + + PolynomialOver& Accumulate(const PolynomialOver& t, const Ring &ring); + PolynomialOver& Reduce(const PolynomialOver& t, const Ring &ring); + + /// + PolynomialOver Doubled(const Ring &ring) const {return Plus(*this, ring);} + /// + PolynomialOver Squared(const Ring &ring) const {return Times(*this, ring);} + + CoefficientType EvaluateAt(const CoefficientType &x, const Ring &ring) const; + + PolynomialOver& ShiftLeft(unsigned int n, const Ring &ring); + PolynomialOver& ShiftRight(unsigned int n, const Ring &ring); + + /// calculate r and q such that (a == d*q + r) && (0 <= degree of r < degree of d) + static void Divide(PolynomialOver &r, PolynomialOver &q, const PolynomialOver &a, const PolynomialOver &d, const Ring &ring); + //@} + + /// \name INPUT/OUTPUT + //@{ + std::istream& Input(std::istream &in, const Ring &ring); + std::ostream& Output(std::ostream &out, const Ring &ring) const; + //@} + +private: + void FromStr(const char *str, const Ring &ring); + + std::vector m_coefficients; +}; + +/// Polynomials over a fixed ring +/*! Having a fixed ring allows overloaded operators */ +template class PolynomialOverFixedRing : private PolynomialOver +{ + typedef PolynomialOver B; + typedef PolynomialOverFixedRing ThisType; + +public: + typedef T Ring; + typedef typename T::Element CoefficientType; + typedef typename B::DivideByZero DivideByZero; + typedef typename B::RandomizationParameter RandomizationParameter; + + /// \name CREATORS + //@{ + /// creates the zero polynomial + PolynomialOverFixedRing(unsigned int count = 0) : B(ms_fixedRing, count) {} + + /// copy constructor + PolynomialOverFixedRing(const ThisType &t) : B(t) {} + + explicit PolynomialOverFixedRing(const B &t) : B(t) {} + + /// construct constant polynomial + PolynomialOverFixedRing(const CoefficientType &element) : B(element) {} + + /// construct polynomial with specified coefficients, starting from coefficient of x^0 + template PolynomialOverFixedRing(Iterator first, Iterator last) + : B(first, last) {} + + /// convert from string + explicit PolynomialOverFixedRing(const char *str) : B(str, ms_fixedRing) {} + + /// convert from big-endian byte array + PolynomialOverFixedRing(const byte *encodedPoly, unsigned int byteCount) : B(encodedPoly, byteCount) {} + + /// convert from Basic Encoding Rules encoded byte array + explicit PolynomialOverFixedRing(const byte *BEREncodedPoly) : B(BEREncodedPoly) {} + + /// convert from BER encoded byte array stored in a BufferedTransformation object + explicit PolynomialOverFixedRing(BufferedTransformation &bt) : B(bt) {} + + /// create a random PolynomialOverFixedRing + PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) : B(rng, parameter, ms_fixedRing) {} + + static const ThisType &Zero(); + static const ThisType &One(); + //@} + + /// \name ACCESSORS + //@{ + /// the zero polynomial will return a degree of -1 + int Degree() const {return B::Degree(ms_fixedRing);} + /// degree + 1 + unsigned int CoefficientCount() const {return B::CoefficientCount(ms_fixedRing);} + /// return coefficient for x^i + CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);} + /// return coefficient for x^i + CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);} + //@} + + /// \name MANIPULATORS + //@{ + /// + ThisType& operator=(const ThisType& t) {B::operator=(t); return *this;} + /// + ThisType& operator+=(const ThisType& t) {Accumulate(t, ms_fixedRing); return *this;} + /// + ThisType& operator-=(const ThisType& t) {Reduce(t, ms_fixedRing); return *this;} + /// + ThisType& operator*=(const ThisType& t) {return *this = *this*t;} + /// + ThisType& operator/=(const ThisType& t) {return *this = *this/t;} + /// + ThisType& operator%=(const ThisType& t) {return *this = *this%t;} + + /// + ThisType& operator<<=(unsigned int n) {ShiftLeft(n, ms_fixedRing); return *this;} + /// + ThisType& operator>>=(unsigned int n) {ShiftRight(n, ms_fixedRing); return *this;} + + /// set the coefficient for x^i to value + void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, ms_fixedRing);} + + /// + void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) {B::Randomize(rng, parameter, ms_fixedRing);} + + /// + void Negate() {B::Negate(ms_fixedRing);} + + void swap(ThisType &t) {B::swap(t);} + //@} + + /// \name UNARY OPERATORS + //@{ + /// + bool operator!() const {return CoefficientCount()==0;} + /// + ThisType operator+() const {return *this;} + /// + ThisType operator-() const {return ThisType(Inverse(ms_fixedRing));} + //@} + + /// \name BINARY OPERATORS + //@{ + /// + friend ThisType operator>>(ThisType a, unsigned int n) {return ThisType(a>>=n);} + /// + friend ThisType operator<<(ThisType a, unsigned int n) {return ThisType(a<<=n);} + //@} + + /// \name OTHER ARITHMETIC FUNCTIONS + //@{ + /// + ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(ms_fixedRing));} + /// + bool IsUnit() const {return B::IsUnit(ms_fixedRing);} + + /// + ThisType Doubled() const {return ThisType(B::Doubled(ms_fixedRing));} + /// + ThisType Squared() const {return ThisType(B::Squared(ms_fixedRing));} + + CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, ms_fixedRing);} + + /// calculate r and q such that (a == d*q + r) && (0 <= r < abs(d)) + static void Divide(ThisType &r, ThisType &q, const ThisType &a, const ThisType &d) + {B::Divide(r, q, a, d, ms_fixedRing);} + //@} + + /// \name INPUT/OUTPUT + //@{ + /// + friend std::istream& operator>>(std::istream& in, ThisType &a) + {return a.Input(in, ms_fixedRing);} + /// + friend std::ostream& operator<<(std::ostream& out, const ThisType &a) + {return a.Output(out, ms_fixedRing);} + //@} + +private: + struct NewOnePolynomial + { + ThisType * operator()() const + { + return new ThisType(ms_fixedRing.MultiplicativeIdentity()); + } + }; + + static const Ring ms_fixedRing; +}; + +/// Ring of polynomials over another ring +template class RingOfPolynomialsOver : public AbstractEuclideanDomain > +{ +public: + typedef T CoefficientRing; + typedef PolynomialOver Element; + typedef typename Element::CoefficientType CoefficientType; + typedef typename Element::RandomizationParameter RandomizationParameter; + + RingOfPolynomialsOver(const CoefficientRing &ring) : m_ring(ring) {} + + Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) + {return Element(rng, parameter, m_ring);} + + bool Equal(const Element &a, const Element &b) const + {return a.Equals(b, m_ring);} + + const Element& Identity() const + {return this->result = m_ring.Identity();} + + const Element& Add(const Element &a, const Element &b) const + {return this->result = a.Plus(b, m_ring);} + + Element& Accumulate(Element &a, const Element &b) const + {a.Accumulate(b, m_ring); return a;} + + const Element& Inverse(const Element &a) const + {return this->result = a.Inverse(m_ring);} + + const Element& Subtract(const Element &a, const Element &b) const + {return this->result = a.Minus(b, m_ring);} + + Element& Reduce(Element &a, const Element &b) const + {return a.Reduce(b, m_ring);} + + const Element& Double(const Element &a) const + {return this->result = a.Doubled(m_ring);} + + const Element& MultiplicativeIdentity() const + {return this->result = m_ring.MultiplicativeIdentity();} + + const Element& Multiply(const Element &a, const Element &b) const + {return this->result = a.Times(b, m_ring);} + + const Element& Square(const Element &a) const + {return this->result = a.Squared(m_ring);} + + bool IsUnit(const Element &a) const + {return a.IsUnit(m_ring);} + + const Element& MultiplicativeInverse(const Element &a) const + {return this->result = a.MultiplicativeInverse(m_ring);} + + const Element& Divide(const Element &a, const Element &b) const + {return this->result = a.DividedBy(b, m_ring);} + + const Element& Mod(const Element &a, const Element &b) const + {return this->result = a.Modulo(b, m_ring);} + + void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const + {Element::Divide(r, q, a, d, m_ring);} + + class InterpolationFailed : public Exception + { + public: + InterpolationFailed() : Exception(OTHER_ERROR, "RingOfPolynomialsOver: interpolation failed") {} + }; + + Element Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const; + + // a faster version of Interpolate(x, y, n).EvaluateAt(position) + CoefficientType InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const; +/* + void PrepareBulkInterpolation(CoefficientType *w, const CoefficientType x[], unsigned int n) const; + void PrepareBulkInterpolationAt(CoefficientType *v, const CoefficientType &position, const CoefficientType x[], const CoefficientType w[], unsigned int n) const; + CoefficientType BulkInterpolateAt(const CoefficientType y[], const CoefficientType v[], unsigned int n) const; +*/ +protected: + void CalculateAlpha(std::vector &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const; + + CoefficientRing m_ring; +}; + +template +void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n); +template +void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n); +template +Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n); + +/// +template +inline bool operator==(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Equals(b, a.ms_fixedRing);} +/// +template +inline bool operator!=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return !(a==b);} + +/// +template +inline bool operator> (const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() > b.Degree();} +/// +template +inline bool operator>=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() >= b.Degree();} +/// +template +inline bool operator< (const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() < b.Degree();} +/// +template +inline bool operator<=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() <= b.Degree();} + +/// +template +inline CryptoPP::PolynomialOverFixedRing operator+(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Plus(b, a.ms_fixedRing));} +/// +template +inline CryptoPP::PolynomialOverFixedRing operator-(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Minus(b, a.ms_fixedRing));} +/// +template +inline CryptoPP::PolynomialOverFixedRing operator*(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Times(b, a.ms_fixedRing));} +/// +template +inline CryptoPP::PolynomialOverFixedRing operator/(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.DividedBy(b, a.ms_fixedRing));} +/// +template +inline CryptoPP::PolynomialOverFixedRing operator%(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Modulo(b, a.ms_fixedRing));} + +NAMESPACE_END + +NAMESPACE_BEGIN(std) +template inline void swap(CryptoPP::PolynomialOver &a, CryptoPP::PolynomialOver &b) +{ + a.swap(b); +} +template inline void swap(CryptoPP::PolynomialOverFixedRing &a, CryptoPP::PolynomialOverFixedRing &b) +{ + a.swap(b); +} +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ppc_simd.h b/third_party/cryptoppwin/include/cryptopp/ppc_simd.h new file mode 100644 index 00000000..a5297cf1 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/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 +/// vec_xl and vec_xst 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 GCC Compile Farm +/// - 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 Vector{FuncName} were +/// renamed to Vec{FuncName}. For example, VectorAnd was +/// changed to VecAnd. 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, VecAdd64 and VecSub64 +/// 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. +///
+///    \#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);
+///    ...
+/// \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 +# 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 vec_add (vaddudm) +/// and vec_sub (vsubudm), 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 +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 +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 +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 vec_ld if the effective address +/// of src is aligned. If unaligned it uses vec_lvsl, +/// vec_ld, vec_perm and src. The fixups using +/// vec_lvsl and vec_perm 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(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 vec_ld if the effective address +/// of src is aligned. If unaligned it uses vec_lvsl, +/// vec_ld, vec_perm and src. +/// \details The fixups using vec_lvsl and vec_perm 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(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 vec_xl 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(src); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl 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(src)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl 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(src); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl 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(src)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl 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(src); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl 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(src)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl if available. +/// vec_ld is used if POWER9 is not available. The effective +/// address of src 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(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 vec_xl if available. +/// vec_ld is used if POWER9 is not available. The effective +/// address of src 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(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 vec_xl if +/// available. vec_ld is used if POWER7 or VSX are not available. +/// The effective address of src 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(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 vec_xl if +/// available. vec_ld is used if POWER7 or VSX are not available. +/// The effective address of src 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(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 vec_xl if +/// available. vec_ld is used if POWER7 or VSX are not available. +/// The effective address of src 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(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 vec_xl if +/// available. vec_ld is used if POWER7 or VSX are not available. +/// The effective address of src 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(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 vec_xl 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(src); + // CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 0); + CRYPTOPP_UNUSED(addr); + +#if defined(_ARCH_PWR9) + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl 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(src)+off; + // CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 0); + CRYPTOPP_UNUSED(addr); + +#if defined(_ARCH_PWR9) + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_st if the effective address +/// of dest is aligned, and uses vec_ste otherwise. +/// vec_ste 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 +inline void VecStore_ALTIVEC(const T data, byte dest[16]) +{ + // Avoid IsAlignedOn for convenience. + uintptr_t addr = reinterpret_cast(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 vec_st if the effective address +/// of dest is aligned, and uses vec_ste otherwise. +/// vec_ste 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 +inline void VecStore_ALTIVEC(const T data, int off, byte dest[16]) +{ + // Avoid IsAlignedOn for convenience. + uintptr_t addr = reinterpret_cast(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 vec_xst 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl if available. +/// vec_st is used if POWER9 is not available. The effective +/// address of dest 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl if available. +/// vec_st is used if POWER9 is not available. The effective +/// address of dest 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl if available. +/// POWER7 vec_xst is used if POWER9 is not available. vec_st +/// is used if POWER7 is not available. The effective address of dest +/// 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xl if available. +/// POWER7 vec_xst is used if POWER9 is not available. vec_st +/// is used if POWER7 is not available. The effective address of dest +/// 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest); + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec_xst 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 +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(dest)+off; + CRYPTOPP_ASSERT(addr % GetAlignmentOf() == 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 vec1 & vec2. +/// 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 +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 vec1 | vec2. +/// 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 +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 vec1 ^ vec2. +/// 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 +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 vec1 + vec2. +/// 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 +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 vec1 - vec2. +/// 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 +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 +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 +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 vec_sld(a, z, +/// c). On little endian machines VecShiftLeftOctet() is translated to +/// vec_sld(z, a, 16-c). You should always call the function as +/// if on a big endian machine as shown below. +///
+///   uint8x16_p x = VecLoad(ptr);
+///   uint8x16_p y = VecShiftLeftOctet<12>(x);
+/// 
+/// \par Wraps +/// vec_sld +/// \sa Is vec_sld +/// endian sensitive? on Stack Overflow +/// \since Crypto++ 6.0 +template +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 vec_sld(a, z, +/// c). On little endian machines VecShiftRightOctet() is translated to +/// vec_sld(z, a, 16-c). You should always call the function as +/// if on a big endian machine as shown below. +///
+///   uint8x16_p x = VecLoad(ptr);
+///   uint8x16_p y = VecShiftRightOctet<12>(y);
+/// 
+/// \par Wraps +/// vec_sld +/// \sa Is vec_sld +/// endian sensitive? on Stack Overflow +/// \since Crypto++ 6.0 +template +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 Is vec_sld +/// endian sensitive? on Stack Overflow +/// \since Crypto++ 6.0 +template +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 Is vec_sld +/// endian sensitive? on Stack Overflow +/// \since Crypto++ 6.0 +template +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 vec1 + vec2. 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 vec1 + vec2. 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 vec1 - vec2. 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 vec1 - vec2. 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 +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((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(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 +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(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(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 +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((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(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 +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(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(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 vec1 & vec2. +/// 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 +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 vec1 | vec2. +/// 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 +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 vec1 ^ vec2. +/// 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 +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 +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 +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 ah*bh XOR +/// al*bl. 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 ah=0 +/// results in 0*bh XOR al*bl = al*bl. +/// \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 ah*bh XOR +/// al*bl. 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 ah=0 +/// results in 0*bh XOR al*bl = al*bl. +/// \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 c = _mm_clmulepi64_si128(a, b, 0x00). +/// The 0x00 indicates the low 64-bits of a and b +/// 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 c = _mm_clmulepi64_si128(a, b, 0x01). +/// The 0x01 indicates the low 64-bits of a and high +/// 64-bits of b 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 c = _mm_clmulepi64_si128(a, b, 0x10). +/// The 0x10 indicates the high 64-bits of a and low +/// 64-bits of b 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 c = _mm_clmulepi64_si128(a, b, 0x11). +/// The 0x11 indicates the high 64-bits of a and b +/// 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 +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 +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 +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 +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 +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 +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 diff --git a/third_party/cryptoppwin/include/cryptopp/pssr.h b/third_party/cryptoppwin/include/cryptopp/pssr.h new file mode 100644 index 00000000..46386227 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/pssr.h @@ -0,0 +1,105 @@ +// pssr.h - originally written and placed in the public domain by Wei Dai + +/// \file pssr.h +/// \brief Classes for probabilistic signature schemes +/// \since Crypto++ 2.1 + +#ifndef CRYPTOPP_PSSR_H +#define CRYPTOPP_PSSR_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "emsa2.h" + +#ifdef CRYPTOPP_IS_DLL +#include "sha.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief PSSR Message Encoding Method interface +/// \since Crypto++ 2.1 +class CRYPTOPP_DLL PSSR_MEM_Base : public PK_RecoverableSignatureMessageEncodingMethod +{ +public: + virtual ~PSSR_MEM_Base() {} + +protected: + virtual bool AllowRecovery() const =0; + virtual size_t SaltLen(size_t hashLen) const =0; + virtual size_t MinPadLen(size_t hashLen) const =0; + virtual const MaskGeneratingFunction & GetMGF() const =0; + +private: + size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const; + size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const; + bool IsProbabilistic() const; + bool AllowNonrecoverablePart() const; + bool RecoverablePartFirst() const; + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; + DecodingResult RecoverMessageFromRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength, + byte *recoverableMessage) const; +}; + +/// \brief PSSR Message Encoding Method with Hash Identifier +/// \tparam USE_HASH_ID flag indicating whether the HashId is used +/// \since Crypto++ 2.1 +template class PSSR_MEM_BaseWithHashId; + +/// \brief PSSR Message Encoding Method with Hash Identifier +/// \details If USE_HASH_ID is true, then EMSA2HashIdLookup is used for the base class +template<> class PSSR_MEM_BaseWithHashId : public EMSA2HashIdLookup {}; + +/// \brief PSSR Message Encoding Method without Hash Identifier +/// \details If USE_HASH_ID is false, then PSSR_MEM_Base is used for the base class +/// \since Crypto++ 2.1 +template<> class PSSR_MEM_BaseWithHashId : public PSSR_MEM_Base {}; + +/// \brief PSSR Message Encoding Method +/// \tparam ALLOW_RECOVERY flag indicating whether the scheme provides message recovery +/// \tparam MGF mask generation function +/// \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 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 +class PSSR_MEM : public PSSR_MEM_BaseWithHashId +{ + virtual bool AllowRecovery() const {return ALLOW_RECOVERY;} + virtual size_t SaltLen(size_t hashLen) const {return SALT_LEN < 0 ? hashLen : SALT_LEN;} + virtual size_t MinPadLen(size_t hashLen) const {return MIN_PAD_LEN < 0 ? hashLen : MIN_PAD_LEN;} + virtual const MaskGeneratingFunction & GetMGF() const {static MGF mgf; return mgf;} + +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(ALLOW_RECOVERY ? "PSSR-" : "PSS-") + MGF::StaticAlgorithmName();} +}; + +/// \brief Probabilistic Signature Scheme with Recovery +/// \details Signature Schemes with Recovery encode the message with the signature. +/// \sa PSSR-MGF1 +/// \since Crypto++ 2.1 +struct PSSR : public SignatureStandard +{ + typedef PSSR_MEM SignatureMessageEncodingMethod; +}; + +/// \brief Probabilistic Signature Scheme with Appendix +/// \details Signature Schemes with Appendix require the message to be provided during verification. +/// \sa PSS-MGF1 +/// \since Crypto++ 2.1 +struct PSS : public SignatureStandard +{ + typedef PSSR_MEM SignatureMessageEncodingMethod; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/pubkey.h b/third_party/cryptoppwin/include/cryptopp/pubkey.h new file mode 100644 index 00000000..bdfeef42 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/pubkey.h @@ -0,0 +1,2378 @@ +// pubkey.h - originally written and placed in the public domain by Wei Dai + +/// \file pubkey.h +/// \brief This file contains helper classes/functions for implementing public key algorithms. +/// \details The class hierarchies in this header file tend to look like this: +/// +///
+///                   x1
+///                  +--+
+///                  |  |
+///                 y1  z1
+///                  |  |
+///             x2  x2
+///                  |  |
+///                 y2  z2
+///                  |  |
+///             x3  x3
+///                  |  |
+///                 y3  z3
+/// 
+/// +///
    +///
  • x1, y1, z1 are abstract interface classes defined in cryptlib.h +///
  • 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. +///
  • x3, y3, z3 hold actual algorithms and implement those virtual functions. +/// These classes have Impl suffixes. +///
+/// +/// \details The TF_ prefix means an implementation using trapdoor functions on integers. +/// \details The DL_ prefix means an implementation using group operations in groups where discrete log is hard. + +#ifndef CRYPTOPP_PUBKEY_H +#define CRYPTOPP_PUBKEY_H + +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4702) +#endif + +#include "cryptlib.h" +#include "integer.h" +#include "algebra.h" +#include "modarith.h" +#include "filters.h" +#include "eprecomp.h" +#include "fips140.h" +#include "argnames.h" +#include "smartptr.h" +#include "stdcpp.h" + +#if defined(__SUNPRO_CC) +# define MAYBE_RETURN(x) return x +#else +# define MAYBE_RETURN(x) CRYPTOPP_UNUSED(x) +#endif + +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. +/// \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. +/// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(), +/// 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 + /// \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 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 + /// \return the maximum size of a message before the trapdoor function is applied bound to a public key + /// \details The default implementation returns PreimageBound() - 1. + virtual Integer MaxPreimage() const {return --PreimageBound();} + /// \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 ImageBound() - 1. + 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. +/// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(), +/// RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds +{ +public: + virtual ~RandomizedTrapdoorFunction() {} + + /// \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 + /// \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. + virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0; + + /// \brief Determines if the encryption algorithm is randomized + /// \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. +/// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(), +/// RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction +{ +public: + virtual ~TrapdoorFunction() {} + + /// \brief Applies the trapdoor function + /// \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() + /// 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 + /// \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. + 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. +/// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(), +/// RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse +{ +public: + virtual ~RandomizedTrapdoorFunctionInverse() {} + + /// \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 + /// \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. + virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0; + + /// \brief Determines if the decryption algorithm is randomized + /// \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. +/// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(), +/// RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse() +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse +{ +public: + virtual ~TrapdoorFunctionInverse() {} + + /// \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 + /// \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() + /// without the RandomNumberGenerator. + Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const + {return CalculateInverse(rng, x);} + + /// \brief Determines if the decryption algorithm is randomized + /// \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 + /// \return the inverse of the element in the group + virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0; +}; + +// ******************************************************** + +/// \brief Message encoding method for public key encryption +class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod +{ +public: + virtual ~PK_EncryptionMessageEncodingMethod() {} + + virtual bool ParameterSupported(const char *name) const + {CRYPTOPP_UNUSED(name); return false;} + + /// max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus) + virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0; + + virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs ¶meters) const =0; + + virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs ¶meters) const =0; +}; + +// ******************************************************** + +/// \brief The base for trapdoor based cryptosystems +/// \tparam TFI trapdoor function interface derived class +/// \tparam MEI message encoding interface derived class +template +class CRYPTOPP_NO_VTABLE TF_Base +{ +protected: + virtual ~TF_Base() {} + + virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0; + + typedef TFI TrapdoorFunctionInterface; + virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0; + + typedef MEI MessageEncodingInterface; + virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0; +}; + +// ******************************************************** + +/// \brief Public key trapdoor function default implementation +/// \tparam BASE public key cryptosystem with a fixed length +template +class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE +{ +public: + virtual ~PK_FixedLengthCryptoSystemImpl() {} + + size_t MaxPlaintextLength(size_t ciphertextLength) const + {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;} + size_t CiphertextLength(size_t plaintextLength) const + {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;} + + virtual size_t FixedMaxPlaintextLength() const =0; + virtual size_t FixedCiphertextLength() const =0; +}; + +/// \brief Trapdoor function cryptosystem base class +/// \tparam INTFACE public key cryptosystem base interface +/// \tparam BASE public key cryptosystem implementation base +template +class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl, protected BASE +{ +public: + virtual ~TF_CryptoSystemBase() {} + + bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);} + size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());} + size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();} + +protected: + size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());} + // Coverity finding on potential overflow/underflow. + size_t PaddedBlockBitLength() const {return SaturatingSubtract(this->GetTrapdoorFunctionBounds().PreimageBound().BitCount(),1U);} +}; + +/// \brief Trapdoor function cryptosystems decryption base class +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase > +{ +public: + virtual ~TF_DecryptorBase() {} + + DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +/// \brief Trapdoor function cryptosystems encryption base class +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase > +{ +public: + virtual ~TF_EncryptorBase() {} + + void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +// ******************************************************** + +// Typedef change due to Clang, http://github.com/weidai11/cryptopp/issues/300 +typedef std::pair 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 (TF_*) and discrete logarithm (DL_*) +/// based schemes. +class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod +{ +public: + virtual ~PK_SignatureMessageEncodingMethod() {} + + virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const + {CRYPTOPP_UNUSED(hashIdentifierLength); CRYPTOPP_UNUSED(digestLength); return 0;} + virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const + {CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(hashIdentifierLength); CRYPTOPP_UNUSED(digestLength); return 0;} + + /// \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(). + /// \sa Bellare and RogawayPSS: + /// Provably Secure Encoding Method for Digital Signatures + bool IsProbabilistic() const + {return true;} + bool AllowNonrecoverablePart() const + {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + virtual bool RecoverablePartFirst() const + {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + + // for verification, DL + virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const + {CRYPTOPP_UNUSED(hash); CRYPTOPP_UNUSED(semisignature); CRYPTOPP_UNUSED(semisignatureLength);} + + // for signature + virtual void ProcessRecoverableMessage(HashTransformation &hash, + const byte *recoverableMessage, size_t recoverableMessageLength, + const byte *presignature, size_t presignatureLength, + SecByteBlock &semisignature) const + { + CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(recoverableMessage); CRYPTOPP_UNUSED(recoverableMessageLength); + CRYPTOPP_UNUSED(presignature); CRYPTOPP_UNUSED(presignatureLength); CRYPTOPP_UNUSED(semisignature); + if (RecoverablePartFirst()) + CRYPTOPP_ASSERT(!"ProcessRecoverableMessage() not implemented"); + } + + virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const =0; + + virtual bool VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const =0; + + virtual DecodingResult RecoverMessageFromRepresentative( // for TF + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength, + byte *recoveredMessage) const + {CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(messageEmpty); + CRYPTOPP_UNUSED(representative); CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(recoveredMessage); + throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + + virtual DecodingResult RecoverMessageFromSemisignature( // for DL + HashTransformation &hash, HashIdentifier hashIdentifier, + const byte *presignature, size_t presignatureLength, + const byte *semisignature, size_t semisignatureLength, + byte *recoveredMessage) const + {CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(presignature); CRYPTOPP_UNUSED(presignatureLength); + CRYPTOPP_UNUSED(semisignature); CRYPTOPP_UNUSED(semisignatureLength); CRYPTOPP_UNUSED(recoveredMessage); + throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + + // VC60 workaround + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier CRYPTOPP_API Lookup() + { + return HashIdentifier(static_cast(NULLPTR), 0); + } + }; + }; +}; + +/// \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. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod +{ +public: + bool VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +/// \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. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod +{ +public: + bool VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +/// \brief Interface for message encoding method for public key signature schemes. +/// \details DL_SignatureMessageEncodingMethod_DSA provides interfaces +/// for message encoding method for DSA. +class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +/// \brief Interface for message encoding method for public key signature schemes. +/// \details DL_SignatureMessageEncodingMethod_NR provides interfaces +/// for message encoding method for Nyberg-Rueppel. +class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +#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. +class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_SM2 : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; +#endif + +/// \brief Interface for message encoding method for public key signature schemes. +/// \details PK_MessageAccumulatorBase provides interfaces +/// for message encoding method. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator +{ +public: + PK_MessageAccumulatorBase() : m_empty(true) {} + + virtual HashTransformation & AccessHash() =0; + + void Update(const byte *input, size_t length) + { + AccessHash().Update(input, length); + m_empty = m_empty && length == 0; + } + + SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature; + Integer m_k, m_s; + bool m_empty; +}; + +/// \brief Interface for message encoding method for public key signature schemes. +/// \details PK_MessageAccumulatorBase provides interfaces +/// for message encoding method. +template +class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder +{ +public: + HashTransformation & AccessHash() {return this->m_object;} +}; + +/// \brief Trapdoor Function (TF) Signature Scheme base class +/// \tparam INTFACE interface +/// \tparam BASE base class +template +class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTFACE, protected BASE +{ +public: + virtual ~TF_SignatureSchemeBase() {} + + size_t SignatureLength() const + {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();} + size_t MaxRecoverableLength() const + {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());} + size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const + {CRYPTOPP_UNUSED(signatureLength); return this->MaxRecoverableLength();} + + bool IsProbabilistic() const + {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();} + bool AllowNonrecoverablePart() const + {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();} + bool RecoverablePartFirst() const + {return this->GetMessageEncodingInterface().RecoverablePartFirst();} + +protected: + size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} + // Coverity finding on potential overflow/underflow. + size_t MessageRepresentativeBitLength() const {return SaturatingSubtract(this->GetTrapdoorFunctionBounds().ImageBound().BitCount(),1U);} + virtual HashIdentifier GetHashIdentifier() const =0; + virtual size_t GetDigestSize() const =0; +}; + +/// \brief Trapdoor Function (TF) Signer base class +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase > +{ +public: + virtual ~TF_SignerBase() {} + + void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const; + size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const; +}; + +/// \brief Trapdoor Function (TF) Verifier base class +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase > +{ +public: + virtual ~TF_VerifierBase() {} + + void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const; + bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; + DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const; +}; + +// ******************************************************** + +/// \brief Trapdoor Function (TF) scheme options +/// \tparam T1 algorithm info class +/// \tparam T2 keys class with public and private key +/// \tparam T3 message encoding class +template +struct TF_CryptoSchemeOptions +{ + typedef T1 AlgorithmInfo; + typedef T2 Keys; + typedef typename Keys::PrivateKey PrivateKey; + typedef typename Keys::PublicKey PublicKey; + typedef T3 MessageEncodingMethod; +}; + +/// \brief Trapdoor Function (TF) signature scheme options +/// \tparam T1 algorithm info class +/// \tparam T2 keys class with public and private key +/// \tparam T3 message encoding class +/// \tparam T4 HashTransformation class +template +struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions +{ + typedef T4 HashFunction; +}; + +/// \brief Trapdoor Function (TF) base implementation +/// \tparam BASE base class +/// \tparam SCHEME_OPTIONS scheme options class +/// \tparam KEY_CLASS key class +template +class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl +{ +public: + typedef SCHEME_OPTIONS SchemeOptions; + typedef KEY_CLASS KeyClass; + + virtual ~TF_ObjectImplBase() {} + + PublicKey & AccessPublicKey() {return AccessKey();} + const PublicKey & GetPublicKey() const {return GetKey();} + + PrivateKey & AccessPrivateKey() {return AccessKey();} + const PrivateKey & GetPrivateKey() const {return GetKey();} + + virtual const KeyClass & GetKey() const =0; + virtual KeyClass & AccessKey() =0; + + const KeyClass & GetTrapdoorFunction() const {return GetKey();} + + PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const + { + CRYPTOPP_UNUSED(rng); + return new PK_MessageAccumulatorImpl; + } + PK_MessageAccumulator * NewVerificationAccumulator() const + { + return new PK_MessageAccumulatorImpl; + } + +protected: + const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const + {return Singleton().Ref();} + const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const + {return GetKey();} + const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const + {return GetKey();} + + // for signature scheme + HashIdentifier GetHashIdentifier() const + { + typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2 L; + return L::Lookup(); + } + size_t GetDigestSize() const + { + typedef typename SchemeOptions::HashFunction H; + return H::DIGESTSIZE; + } +}; + +/// \brief Trapdoor Function (TF) signature with external reference +/// \tparam BASE base class +/// \tparam SCHEME_OPTIONS scheme options class +/// \tparam KEY key class +/// \details TF_ObjectImplExtRef() holds a pointer to an external key structure +template +class TF_ObjectImplExtRef : public TF_ObjectImplBase +{ +public: + virtual ~TF_ObjectImplExtRef() {} + + TF_ObjectImplExtRef(const KEY *pKey = NULLPTR) : m_pKey(pKey) {} + void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;} + + const KEY & GetKey() const {return *m_pKey;} + KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");} + +private: + const KEY * m_pKey; +}; + +/// \brief Trapdoor Function (TF) signature scheme options +/// \tparam BASE base class +/// \tparam SCHEME_OPTIONS scheme options class +/// \tparam KEY_CLASS key class +/// \details TF_ObjectImpl() holds a reference to a trapdoor function +template +class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase +{ +public: + typedef KEY_CLASS KeyClass; + + virtual ~TF_ObjectImpl() {} + + const KeyClass & GetKey() const {return m_trapdoorFunction;} + KeyClass & AccessKey() {return m_trapdoorFunction;} + +private: + KeyClass m_trapdoorFunction; +}; + +/// \brief Trapdoor Function (TF) decryptor options +/// \tparam SCHEME_OPTIONS scheme options class +template +class TF_DecryptorImpl : public TF_ObjectImpl +{ +}; + +/// \brief Trapdoor Function (TF) encryptor options +/// \tparam SCHEME_OPTIONS scheme options class +template +class TF_EncryptorImpl : public TF_ObjectImpl +{ +}; + +/// \brief Trapdoor Function (TF) encryptor options +/// \tparam SCHEME_OPTIONS scheme options class +template +class TF_SignerImpl : public TF_ObjectImpl +{ +}; + +/// \brief Trapdoor Function (TF) encryptor options +/// \tparam SCHEME_OPTIONS scheme options class +template +class TF_VerifierImpl : public TF_ObjectImpl +{ +}; + +// ******************************************************** + +/// \brief Mask generation function interface +/// \sa P1363_KDF2, P1363_MGF1 +/// \since Crypto++ 2.0 +class CRYPTOPP_NO_VTABLE MaskGeneratingFunction +{ +public: + virtual ~MaskGeneratingFunction() {} + + /// \brief Generate and apply mask + /// \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 + virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0; +}; + +/// \fn P1363_MGF1KDF2_Common +/// \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 derivationParams additional derivation parameters +/// \param derivationParamsLength the size of the additional derivation parameters +/// \param mask flag indicating whether to apply the mask +/// \param counterStart starting counter value used in generation function +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); + } +}; + +// ******************************************************** + +/// \brief P1363 key derivation function +/// \tparam H hash function used in the derivation +/// \sa P1363_MGF1, KeyDerivationFunction, P1363_KDF2 +/// on the Crypto++ wiki +/// \since Crypto++ 2.0 +template +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; + P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1); + } +}; + +// ******************************************************** + +/// \brief Exception thrown when an invalid group element is encountered +/// \details Thrown by DecodeElement and AgreeWithStaticPrivateKey +class DL_BadElement : public InvalidDataFormat +{ +public: + DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {} +}; + +/// \brief Interface for Discrete Log (DL) group parameters +/// \tparam T element in the group +/// \details The element is usually an Integer, \ref ECP "ECP::Point" or \ref EC2N "EC2N::Point" +template +class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters +{ + typedef DL_GroupParameters ThisClass; + +public: + typedef T Element; + + virtual ~DL_GroupParameters() {} + + DL_GroupParameters() : m_validationLevel(0) {} + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const + { + if (!GetBasePrecomputation().IsInitialized()) + return false; + + 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; + + return pass; + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper(this, name, valueType, pValue) + CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder) + CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator) + ; + } + + /// \brief Determines whether the object supports precomputation + /// \return true if the object supports precomputation, false otherwise + /// \sa Precompute() + bool SupportsPrecomputation() const {return true;} + + /// \brief Perform precomputation + /// \param precomputationStorage the suggested number of objects for the precompute table + /// \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. + /// \details If a derived class does not override Precompute(), then the base class throws + /// NotImplemented. + /// \sa SupportsPrecomputation(), LoadPrecomputation(), SavePrecomputation() + void Precompute(unsigned int precomputationStorage=16) + { + AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage); + } + + /// \brief Retrieve previously saved precomputation + /// \param storedPrecomputation BufferedTransformation with the saved precomputation + /// \throw NotImplemented + /// \sa SupportsPrecomputation(), Precompute() + void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + { + AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation); + m_validationLevel = 0; + } + + /// \brief Save precomputation for later use + /// \param storedPrecomputation BufferedTransformation to write the precomputation + /// \throw NotImplemented + /// \sa SupportsPrecomputation(), Precompute() + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + { + GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation); + } + + /// \brief Retrieves the subgroup generator + /// \return the subgroup generator + /// \details The subgroup generator is retrieved from the base precomputation + virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());} + + /// \brief Sets the subgroup generator + /// \param base the new subgroup generator + /// \details The subgroup generator is set in the base precomputation + virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);} + + /// \brief Exponentiates the base + /// \return the element after exponentiation + /// \details ExponentiateBase() calls GetBasePrecomputation() and then exponentiates. + virtual Element ExponentiateBase(const Integer &exponent) const + { + return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent); + } + + /// \brief Exponentiates an element + /// \param base the base element + /// \param exponent the exponent to raise the base + /// \return the result of the exponentiation + /// \details Internally, ExponentiateElement() calls SimultaneousExponentiate(). + virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const + { + Element result; + SimultaneousExponentiate(&result, base, &exponent, 1); + return result; + } + + /// \brief Retrieves the group precomputation + /// \return a const reference to the group precomputation + virtual const DL_GroupPrecomputation & GetGroupPrecomputation() const =0; + + /// \brief Retrieves the group precomputation + /// \return a const reference to the group precomputation using a fixed base + virtual const DL_FixedBasePrecomputation & GetBasePrecomputation() const =0; + + /// \brief Retrieves the group precomputation + /// \return a non-const reference to the group precomputation using a fixed base + virtual DL_FixedBasePrecomputation & AccessBasePrecomputation() =0; + + /// \brief Retrieves the subgroup order + /// \return the order of subgroup generated by the base element + virtual const Integer & GetSubgroupOrder() const =0; + + /// \brief Retrieves the maximum exponent for the group + /// \return the maximum exponent for the group + virtual Integer GetMaxExponent() const =0; + + /// \brief Retrieves the order of the group + /// \return the order of the group + /// \details Either GetGroupOrder() or GetCofactor() must be overridden in a derived class. + virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();} + + /// \brief Retrieves the cofactor + /// \return the cofactor + /// \details Either GetGroupOrder() or GetCofactor() must be overridden in a derived class. + virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();} + + /// \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 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; + + /// \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 COUNTOF(encoded) == GetEncodedElementSize() + virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0; + + /// \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 COUNTOF(encoded) == GetEncodedElementSize() + virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0; + + /// \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. + virtual Integer ConvertElementToInteger(const Element &element) const =0; + + /// \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 There are four levels of thoroughness: + ///
    + ///
  • 0 - using this object won't cause a crash or exception + ///
  • 1 - this object will probably function, and encrypt, sign, other operations correctly + ///
  • 2 - ensure this object will function correctly, and perform reasonable security checks + ///
  • 3 - perform reasonable security checks, and do checks that may take a long time + ///
+ /// \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. + /// \details ValidateGroup() must be implemented in a derived class. + virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0; + + /// \brief Check the element for errors + /// \param level level of thoroughness + /// \param element element to check + /// \param precomp optional pointer to DL_FixedBasePrecomputation + /// \return true if the tests succeed, false otherwise + /// \details There are four levels of thoroughness: + ///
    + ///
  • 0 - using this object won't cause a crash or exception + ///
  • 1 - this object will probably function, and encrypt, sign, other operations correctly + ///
  • 2 - ensure this object will function correctly, and perform reasonable security checks + ///
  • 3 - perform reasonable security checks, and do checks that may take a long time + ///
+ /// \details Level 0 performs group membership checks. Level 1 may not check for weak keys and such. + /// 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 *precomp) const =0; + + virtual bool FastSubgroupCheckAvailable() const =0; + + /// \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. + virtual bool IsIdentity(const Element &element) const =0; + + /// \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 COUNTOF(results) == exponentsCount + /// \pre COUNTOF(exponents) == exponentsCount + virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0; + +protected: + void ParametersChanged() {m_validationLevel = 0;} + +private: + mutable unsigned int m_validationLevel; +}; + +/// \brief Base implementation of Discrete Log (DL) group parameters +/// \tparam GROUP_PRECOMP group precomputation class +/// \tparam BASE_PRECOMP fixed base precomputation class +/// \tparam BASE class or type of an element +template , class BASE = DL_GroupParameters > +class DL_GroupParametersImpl : public BASE +{ +public: + typedef GROUP_PRECOMP GroupPrecomputation; + typedef typename GROUP_PRECOMP::Element Element; + typedef BASE_PRECOMP BasePrecomputation; + + virtual ~DL_GroupParametersImpl() {} + + /// \brief Retrieves the group precomputation + /// \return a const reference to the group precomputation + const DL_GroupPrecomputation & GetGroupPrecomputation() const {return m_groupPrecomputation;} + + /// \brief Retrieves the group precomputation + /// \return a const reference to the group precomputation using a fixed base + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return m_gpc;} + + /// \brief Retrieves the group precomputation + /// \return a non-const reference to the group precomputation using a fixed base + DL_FixedBasePrecomputation & AccessBasePrecomputation() {return m_gpc;} + +protected: + GROUP_PRECOMP m_groupPrecomputation; + BASE_PRECOMP m_gpc; +}; + +/// \brief Base class for a Discrete Log (DL) key +/// \tparam T class or type of an element +/// \details The element is usually an Integer, \ref ECP "ECP::Point" or \ref EC2N "EC2N::Point" +template +class CRYPTOPP_NO_VTABLE DL_Key +{ +public: + virtual ~DL_Key() {} + + /// \brief Retrieves abstract group parameters + /// \return a const reference to the group parameters + virtual const DL_GroupParameters & GetAbstractGroupParameters() const =0; + /// \brief Retrieves abstract group parameters + /// \return a non-const reference to the group parameters + virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; +}; + +/// \brief Interface for Discrete Log (DL) public keys +template +class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key +{ + typedef DL_PublicKey ThisClass; + +public: + typedef T Element; + + virtual ~DL_PublicKey(); + + /// \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(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) + CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement); + } + + /// \brief Initialize or reinitialize this key + /// \param source NameValuePairs to assign + void AssignFrom(const NameValuePairs &source); + + /// \brief Retrieves the public element + /// \return the public element + virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());} + + /// \brief Sets the public element + /// \param y the public element + virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);} + + /// \brief Exponentiates this element + /// \param exponent the exponent to raise the base + /// \return the public element raised to the exponent + virtual Element ExponentiatePublicElement(const Integer &exponent) const + { + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent); + } + + /// \brief Exponentiates an element + /// \param baseExp the first exponent + /// \param publicExp the second exponent + /// \return the public element raised to the exponent + /// \details CascadeExponentiateBaseAndPublicElement raises the public element to + /// the base element and precomputation. + virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const + { + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp); + } + + /// \brief Accesses the public precomputation + /// \details GetPublicPrecomputation returns a const reference, while + /// AccessPublicPrecomputation returns a non-const reference. Must be + /// overridden in derived classes. + virtual const DL_FixedBasePrecomputation & 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. + virtual DL_FixedBasePrecomputation & AccessPublicPrecomputation() =0; +}; + +// Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499 +template +DL_PublicKey::~DL_PublicKey() {} + +/// \brief Interface for Discrete Log (DL) private keys +template +class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key +{ + typedef DL_PrivateKey ThisClass; + +public: + typedef T Element; + + virtual ~DL_PrivateKey(); + + /// \brief Initializes a public key from this key + /// \param pub reference to a public key + void MakePublicKey(DL_PublicKey &pub) const + { + pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters()); + pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent())); + } + + /// \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(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) + CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent); + } + + /// \brief Initialize or reinitialize this key + /// \param source NameValuePairs to assign + void AssignFrom(const NameValuePairs &source) + { + this->AccessAbstractGroupParameters().AssignFrom(source); + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent); + } + + /// \brief Retrieves 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 + /// \param x the private exponent + /// \details Must be overridden in derived classes. + virtual void SetPrivateExponent(const Integer &x) =0; +}; + +// Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499 +template +DL_PrivateKey::~DL_PrivateKey() {} + +template +void DL_PublicKey::AssignFrom(const NameValuePairs &source) +{ + DL_PrivateKey *pPrivateKey = NULLPTR; + if (source.GetThisPointer(pPrivateKey)) + pPrivateKey->MakePublicKey(*this); + else + { + this->AccessAbstractGroupParameters().AssignFrom(source); + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement); + } +} + +class OID; + +/// \brief Discrete Log (DL) key base implementation +/// \tparam PK Key class +/// \tparam GP GroupParameters class +/// \tparam O OID class +template +class DL_KeyImpl : public PK +{ +public: + typedef GP GroupParameters; + + virtual ~DL_KeyImpl() {} + + O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();} + bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) + {AccessGroupParameters().BERDecode(bt); return true;} + bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const + {GetGroupParameters().DEREncode(bt); return true;} + + const GP & GetGroupParameters() const {return m_groupParameters;} + GP & AccessGroupParameters() {return m_groupParameters;} + +private: + GP m_groupParameters; +}; + +class X509PublicKey; +class PKCS8PrivateKey; + +/// \brief Discrete Log (DL) private key base implementation +/// \tparam GP GroupParameters class +template +class DL_PrivateKeyImpl : public DL_PrivateKey, public DL_KeyImpl +{ +public: + typedef typename GP::Element Element; + + virtual ~DL_PrivateKeyImpl() {} + + // 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; + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper >(this, name, valueType, pValue).Assignable(); + } + + void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper >(this, source); + } + + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) + { + if (!params.GetThisObject(this->AccessGroupParameters())) + this->AccessGroupParameters().GenerateRandom(rng, params); + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + SetPrivateExponent(x); + } + + bool SupportsPrecomputation() const {return true;} + + void Precompute(unsigned int precomputationStorage=16) + {AccessAbstractGroupParameters().Precompute(precomputationStorage);} + + void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);} + + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);} + + // DL_Key + const DL_GroupParameters & GetAbstractGroupParameters() const {return this->GetGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} + + // DL_PrivateKey + const Integer & GetPrivateExponent() const {return m_x;} + void SetPrivateExponent(const Integer &x) {m_x = x;} + + // PKCS8PrivateKey + void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) + {m_x.BERDecode(bt);} + void DEREncodePrivateKey(BufferedTransformation &bt) const + {m_x.DEREncode(bt);} + +private: + Integer m_x; +}; + +template +class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE +{ +public: + virtual ~DL_PrivateKey_WithSignaturePairwiseConsistencyTest() {} + + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) + { + BASE::GenerateRandom(rng, params); + + if (FIPS_140_2_ComplianceEnabled()) + { + typename SIGNATURE_SCHEME::Signer signer(*this); + typename SIGNATURE_SCHEME::Verifier verifier(signer); + SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); + } + } +}; + +/// \brief Discrete Log (DL) public key base implementation +/// \tparam GP GroupParameters class +template +class DL_PublicKeyImpl : public DL_PublicKey, public DL_KeyImpl +{ +public: + typedef typename GP::Element Element; + + virtual ~DL_PublicKeyImpl(); + + // 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; + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper >(this, name, valueType, pValue).Assignable(); + } + + void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper >(this, source); + } + + bool SupportsPrecomputation() const {return true;} + + void Precompute(unsigned int precomputationStorage=16) + { + AccessAbstractGroupParameters().Precompute(precomputationStorage); + AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage); + } + + void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + { + AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation); + AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); + } + + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + { + GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation); + GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); + } + + // DL_Key + const DL_GroupParameters & GetAbstractGroupParameters() const {return this->GetGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} + + // DL_PublicKey + const DL_FixedBasePrecomputation & GetPublicPrecomputation() const {return m_ypc;} + DL_FixedBasePrecomputation & AccessPublicPrecomputation() {return m_ypc;} + + // non-inherited + bool operator==(const DL_PublicKeyImpl &rhs) const + {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();} + +private: + typename GP::BasePrecomputation m_ypc; +}; + +// Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499 +template +DL_PublicKeyImpl::~DL_PublicKeyImpl() {} + +/// \brief Interface for Elgamal-like signature algorithms +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +template +class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm +{ +public: + virtual ~DL_ElgamalLikeSignatureAlgorithm() {} + + /// \brief Sign a message using a private key + /// \param params GroupParameters + /// \param privateKey private key + /// \param k signing exponent + /// \param e encoded message + /// \param r r part of signature + /// \param s s part of signature + virtual void Sign(const DL_GroupParameters ¶ms, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0; + + /// \brief Verify a message using a public key + /// \param params GroupParameters + /// \param publicKey public key + /// \param e encoded message + /// \param r r part of signature + /// \param s s part of signature + virtual bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0; + + /// \brief Recover a Presignature + /// \param params GroupParameters + /// \param publicKey public key + /// \param r r part of signature + /// \param s s part of signature + virtual Integer RecoverPresignature(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &r, const Integer &s) const + { + CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(publicKey); CRYPTOPP_UNUSED(r); CRYPTOPP_UNUSED(s); + throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery"); + MAYBE_RETURN(Integer::Zero()); + } + + /// \brief Retrieve R length + /// \param params GroupParameters + virtual size_t RLen(const DL_GroupParameters ¶ms) const + {return params.GetSubgroupOrder().ByteCount();} + + /// \brief Retrieve S length + /// \param params GroupParameters + virtual size_t SLen(const DL_GroupParameters ¶ms) const + {return params.GetSubgroupOrder().ByteCount();} + + /// \brief Signature scheme flag + /// \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;} +}; + +/// \brief Interface for deterministic signers +/// \details RFC 6979 signers which generate k based on the encoded message and private key +class CRYPTOPP_NO_VTABLE DeterministicSignatureAlgorithm +{ +public: + virtual ~DeterministicSignatureAlgorithm() {} + + /// \brief Generate k + /// \param x private key + /// \param q subgroup generator + /// \param e encoded message + virtual Integer GenerateRandom(const Integer &x, const Integer &q, const Integer &e) const =0; +}; + +/// \brief Interface for DL key agreement algorithms +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +/// \sa DLIES, ECIES, ECIES_P1363 +template +class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm +{ +public: + typedef T Element; + + virtual ~DL_KeyAgreementAlgorithm() {} + + virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const =0; + virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0; +}; + +/// \brief Interface for key derivation algorithms used in DL cryptosystems +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +/// \sa DLIES, ECIES, ECIES_P1363 +template +class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm +{ +public: + virtual ~DL_KeyDerivationAlgorithm() {} + + virtual bool ParameterSupported(const char *name) const + {CRYPTOPP_UNUSED(name); return false;} + virtual void Derive(const DL_GroupParameters &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0; +}; + +/// \brief Interface for symmetric encryption algorithms used in DL cryptosystems +/// \sa DLIES, ECIES, ECIES_P1363 +class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm +{ +public: + virtual ~DL_SymmetricEncryptionAlgorithm() {} + + virtual bool ParameterSupported(const char *name) const + {CRYPTOPP_UNUSED(name); return false;} + virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0; + virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0; + virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0; + virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const =0; + virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const =0; +}; + +/// \brief Discrete Log (DL) base interface +/// \tparam KI public or private key interface +template +class CRYPTOPP_NO_VTABLE DL_Base +{ +protected: + typedef KI KeyInterface; + typedef typename KI::Element Element; + + virtual ~DL_Base() {} + + const DL_GroupParameters & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();} + + virtual KeyInterface & AccessKeyInterface() =0; + virtual const KeyInterface & GetKeyInterface() const =0; +}; + +/// \brief Discrete Log (DL) signature scheme base implementation +/// \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 is used for signers, and DL_Base is used for verifiers. +template +class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTFACE, public DL_Base +{ +public: + virtual ~DL_SignatureSchemeBase() {} + + /// \brief Provides the signature length + /// \return signature length, in bytes + /// \details SignatureLength returns the size required for r+s. + size_t SignatureLength() const + { + return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters()) + + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters()); + } + + /// \brief Provides the maximum recoverable length + /// \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 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 + /// \return true if the scheme is probabilistic, false otherwise + bool IsProbabilistic() const + {return true;} + + /// \brief Determines if the scheme has non-recoverable part + /// \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 + /// \return true if the message encoding allows the recoverable part, false otherwise. + bool RecoverablePartFirst() const + {return GetMessageEncodingInterface().RecoverablePartFirst();} + +protected: + size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} + size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();} + + // true if the scheme conforms to RFC 6979 + virtual bool IsDeterministic() const {return false;} + + virtual const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const =0; + virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0; + virtual HashIdentifier GetHashIdentifier() const =0; + virtual size_t GetDigestSize() const =0; +}; + +/// \brief Discrete Log (DL) signature scheme signer base implementation +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +template +class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase > +{ +public: + virtual ~DL_SignerBase() {} + + /// \brief Testing interface + /// \param k Integer + /// \param e Integer + /// \param r Integer + /// \param s Integer + void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const + { + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &key = this->GetKeyInterface(); + + r = params.ConvertElementToInteger(params.ExponentiateBase(k)); + alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); + } + + void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const + { + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); + this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(), + recoverableMessage, recoverableMessageLength, + ma.m_presignature, ma.m_presignature.size(), + ma.m_semisignature); + } + + size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const + { + this->GetMaterial().DoQuickSanityCheck(); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &key = this->GetKeyInterface(); + + SecByteBlock representative(this->MessageRepresentativeLength()); + this->GetMessageEncodingInterface().ComputeMessageRepresentative( + rng, + ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, + representative, this->MessageRepresentativeBitLength()); + ma.m_empty = true; + Integer e(representative, representative.size()); + + // hash message digest into random number k to prevent reusing the same k on + // different messages after virtual machine rollback + if (rng.CanIncorporateEntropy()) + rng.IncorporateEntropy(representative, representative.size()); + + Integer k, ks; + const Integer& q = params.GetSubgroupOrder(); + if (alg.IsDeterministic()) + { + const Integer& x = key.GetPrivateExponent(); + const DeterministicSignatureAlgorithm& det = dynamic_cast(alg); + k = det.GenerateRandom(x, q, e); + } + else + { + 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(ks)); + alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); + + /* + Integer r, s; + if (this->MaxRecoverableLength() > 0) + r.Decode(ma.m_semisignature, ma.m_semisignature.size()); + else + r.Decode(ma.m_presignature, ma.m_presignature.size()); + alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s); + */ + + const size_t rLen = alg.RLen(params); + r.Encode(signature, rLen); + s.Encode(signature+rLen, alg.SLen(params)); + + if (restart) + RestartMessageAccumulator(rng, ma); + + return this->SignatureLength(); + } + +protected: + void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const + { + // k needs to be generated before hashing for signature schemes with recovery + // but to defend against VM rollbacks we need to generate k after hashing. + // so this code is commented out, since no DL-based signature scheme with recovery + // has been implemented in Crypto++ anyway + /* + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1); + ma.m_presignature.New(params.GetEncodedElementSize(false)); + params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size()); + */ + CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(ma); + } +}; + +/// \brief Discret Log (DL) Verifier base class +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +template +class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase > +{ +public: + virtual ~DL_VerifierBase() {} + + void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const + { + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + + // 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, sLen); + + this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size()); + } + + bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const + { + this->GetMaterial().DoQuickSanityCheck(); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &key = this->GetKeyInterface(); + + SecByteBlock representative(this->MessageRepresentativeLength()); + this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, + representative, this->MessageRepresentativeBitLength()); + ma.m_empty = true; + Integer e(representative, representative.size()); + + Integer r(ma.m_semisignature, ma.m_semisignature.size()); + return alg.Verify(params, key, e, r, ma.m_s); + } + + DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const + { + this->GetMaterial().DoQuickSanityCheck(); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &key = this->GetKeyInterface(); + + SecByteBlock representative(this->MessageRepresentativeLength()); + this->GetMessageEncodingInterface().ComputeMessageRepresentative( + NullRNG(), + ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, + representative, this->MessageRepresentativeBitLength()); + ma.m_empty = true; + Integer e(representative, representative.size()); + + ma.m_presignature.New(params.GetEncodedElementSize(false)); + Integer r(ma.m_semisignature, ma.m_semisignature.size()); + alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size()); + + return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature( + ma.AccessHash(), this->GetHashIdentifier(), + ma.m_presignature, ma.m_presignature.size(), + ma.m_semisignature, ma.m_semisignature.size(), + recoveredMessage); + } +}; + +/// \brief Discrete Log (DL) cryptosystem base implementation +/// \tparam PK field element type +/// \tparam KI public or private key interface +template +class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base +{ +public: + typedef typename DL_Base::Element Element; + + virtual ~DL_CryptoSystemBase() {} + + size_t MaxPlaintextLength(size_t ciphertextLength) const + { + unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true); + return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen); + } + + size_t CiphertextLength(size_t plaintextLength) const + { + size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength); + return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len; + } + + bool ParameterSupported(const char *name) const + {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);} + +protected: + virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0; + virtual const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const =0; + virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0; +}; + +/// \brief Discrete Log (DL) decryptor base implementation +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +template +class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase > +{ +public: + typedef T Element; + + virtual ~DL_DecryptorBase() {} + + DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + { + try + { + CRYPTOPP_UNUSED(rng); + const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); + const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); + const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &key = this->GetKeyInterface(); + + Element q = params.DecodeElement(ciphertext, true); + size_t elementSize = params.GetEncodedElementSize(true); + ciphertext += elementSize; + ciphertextLength -= elementSize; + + Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent()); + + SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength))); + derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); + + return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters); + } + catch (DL_BadElement &) + { + return DecodingResult(); + } + } +}; + +/// \brief Discrete Log (DL) encryptor base implementation +/// \tparam T Field element type or class +/// \details Field element T can be Integer, ECP or EC2N. +template +class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase > +{ +public: + typedef T Element; + + virtual ~DL_EncryptorBase() {} + + void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + { + const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); + const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); + const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &key = this->GetKeyInterface(); + + Integer x(rng, Integer::One(), params.GetMaxExponent()); + Element q = params.ExponentiateBase(x); + params.EncodeElement(true, q, ciphertext); + unsigned int elementSize = params.GetEncodedElementSize(true); + ciphertext += elementSize; + + Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x); + + SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength)); + derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); + + encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters); + } +}; + +/// \brief Discrete Log (DL) scheme options +/// \tparam T1 algorithm information +/// \tparam T2 group parameters for the scheme +template +struct DL_SchemeOptionsBase +{ + typedef T1 AlgorithmInfo; + typedef T2 GroupParameters; + typedef typename GroupParameters::Element Element; +}; + +/// \brief Discrete Log (DL) key options +/// \tparam T1 algorithm information +/// \tparam T2 keys used in the scheme +template +struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase +{ + typedef T2 Keys; + typedef typename Keys::PrivateKey PrivateKey; + typedef typename Keys::PublicKey PublicKey; +}; + +/// \brief Discrete Log (DL) signature scheme options +/// \tparam T1 algorithm information +/// \tparam T2 keys used in the scheme +/// \tparam T3 signature algorithm +/// \tparam T4 message encoding method +/// \tparam T5 hash function +template +struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions +{ + typedef T3 SignatureAlgorithm; + typedef T4 MessageEncodingMethod; + typedef T5 HashFunction; +}; + +/// \brief Discrete Log (DL) crypto scheme options +/// \tparam T1 algorithm information +/// \tparam T2 keys used in the scheme +/// \tparam T3 key agreement algorithm +/// \tparam T4 key derivation algorithm +/// \tparam T5 symmetric encryption algorithm +template +struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions +{ + typedef T3 KeyAgreementAlgorithm; + typedef T4 KeyDerivationAlgorithm; + typedef T5 SymmetricEncryptionAlgorithm; +}; + +/// \brief Discrete Log (DL) base object implementation +/// \tparam BASE TODO +/// \tparam SCHEME_OPTIONS options for the scheme +/// \tparam KEY key used in the scheme +template +class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl +{ +public: + typedef SCHEME_OPTIONS SchemeOptions; + typedef typename KEY::Element Element; + + virtual ~DL_ObjectImplBase() {} + + PrivateKey & AccessPrivateKey() {return m_key;} + PublicKey & AccessPublicKey() {return m_key;} + + // KeyAccessor + const KEY & GetKey() const {return m_key;} + KEY & AccessKey() {return m_key;} + +protected: + typename BASE::KeyInterface & AccessKeyInterface() {return m_key;} + const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;} + + // for signature scheme + HashIdentifier GetHashIdentifier() const + { + typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup; + return HashLookup::template HashIdentifierLookup2::Lookup(); + } + size_t GetDigestSize() const + { + typedef typename SchemeOptions::HashFunction H; + return H::DIGESTSIZE; + } + +private: + KEY m_key; +}; + +/// \brief Discrete Log (DL) object implementation +/// \tparam BASE TODO +/// \tparam SCHEME_OPTIONS options for the scheme +/// \tparam KEY key used in the scheme +template +class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase +{ +public: + typedef typename KEY::Element Element; + + virtual ~DL_ObjectImpl() {} + +protected: + const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const + {return Singleton().Ref();} + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const + {return Singleton().Ref();} + const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const + {return Singleton().Ref();} + const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const + {return Singleton().Ref();} + HashIdentifier GetHashIdentifier() const + {return HashIdentifier();} + const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const + {return Singleton().Ref();} +}; + +/// \brief Discrete Log (DL) signer implementation +/// \tparam SCHEME_OPTIONS options for the scheme +template +class DL_SignerImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> +{ +public: + PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const + { + member_ptr p(new PK_MessageAccumulatorImpl); + this->RestartMessageAccumulator(rng, *p); + return p.release(); + } +}; + +/// \brief Discrete Log (DL) verifier implementation +/// \tparam SCHEME_OPTIONS options for the scheme +template +class DL_VerifierImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> +{ +public: + PK_MessageAccumulator * NewVerificationAccumulator() const + { + return new PK_MessageAccumulatorImpl; + } +}; + +/// \brief Discrete Log (DL) encryptor implementation +/// \tparam SCHEME_OPTIONS options for the scheme +template +class DL_EncryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> +{ +}; + +/// \brief Discrete Log (DL) decryptor implementation +/// \tparam SCHEME_OPTIONS options for the scheme +template +class DL_DecryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> +{ +}; + +// ******************************************************** + +/// \brief Discrete Log (DL) simple key agreement base implementation +/// \tparam T class or type +template +class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain +{ +public: + typedef T Element; + + virtual ~DL_SimpleKeyAgreementDomainBase() {} + + CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} + unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} + unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} + unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} + + void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + x.Encode(privateKey, PrivateKeyLength()); + } + + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + CRYPTOPP_UNUSED(rng); + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, PrivateKeyLength()); + Element y = params.ExponentiateBase(x); + params.EncodeElement(true, y, publicKey); + } + + bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const + { + try + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, PrivateKeyLength()); + Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey); + + Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey( + GetAbstractGroupParameters(), w, validateOtherPublicKey, x); + params.EncodeElement(false, z, agreedValue); + } + catch (DL_BadElement &) + { + return false; + } + return true; + } + + /// \brief Retrieves a reference to the group generator + /// \return const reference to the group generator + const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();} + +protected: + virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0; + virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; + const DL_GroupParameters & GetAbstractGroupParameters() const {return const_cast *>(this)->AccessAbstractGroupParameters();} +}; + +/// \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 Methods for Avoiding the "Small-Subgroup" Attacks on the +/// Diffie-Hellman Key Agreement Method for S/MIME +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_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. + INCOMPATIBLE_COFACTOR_MULTIPLICTION}; + +typedef EnumToType NoCofactorMultiplication; +typedef EnumToType CompatibleCofactorMultiplication; +typedef EnumToType IncompatibleCofactorMultiplication; + +/// \brief Diffie-Hellman key agreement algorithm +template +class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm +{ +public: + typedef ELEMENT Element; + + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() + {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";} + + virtual ~DL_KeyAgreementAlgorithm_DH() {} + + Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const + { + return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(), + COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent); + } + + Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const + { + if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) + { + const Integer &k = params.GetCofactor(); + return params.ExponentiateElement(publicElement, + ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k); + } + else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION) + return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor()); + else + { + CRYPTOPP_ASSERT(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION); + + if (!validateOtherPublicKey) + return params.ExponentiateElement(publicElement, privateExponent); + + if (params.FastSubgroupCheckAvailable()) + { + if (!params.ValidateElement(2, publicElement, NULLPTR)) + throw DL_BadElement(); + return params.ExponentiateElement(publicElement, privateExponent); + } + else + { + const Integer e[2] = {params.GetSubgroupOrder(), privateExponent}; + Element r[2]; + params.SimultaneousExponentiate(r, publicElement, e, 2); + if (!params.IsIdentity(r[0])) + throw DL_BadElement(); + return r[1]; + } + } + } +}; + +// ******************************************************** + +/// \brief Template implementing constructors for public key algorithm classes +template +class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE +{ +public: + PK_FinalTemplate() {} + + PK_FinalTemplate(const CryptoMaterial &key) + {this->AccessKey().AssignFrom(key);} + + PK_FinalTemplate(BufferedTransformation &bt) + {this->AccessKey().BERDecode(bt);} + + PK_FinalTemplate(const AsymmetricAlgorithm &algorithm) + {this->AccessKey().AssignFrom(algorithm.GetMaterial());} + + PK_FinalTemplate(const Integer &v1) + {this->AccessKey().Initialize(v1);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} +}; + +/// \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. +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. +struct SignatureStandard {}; + +/// \brief Trapdoor Function (TF) encryption scheme +/// \tparam STANDARD standard +/// \tparam KEYS keys used in the encryption scheme +/// \tparam ALG_INFO algorithm information +template +class TF_ES; + +template > +class TF_ES : public KEYS +{ + typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod; + +public: + /// see EncryptionStandard for a list of standards + typedef STANDARD Standard; + typedef TF_CryptoSchemeOptions SchemeOptions; + + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();} + + /// implements PK_Decryptor interface + typedef PK_FinalTemplate > Decryptor; + /// implements PK_Encryptor interface + typedef PK_FinalTemplate > Encryptor; +}; + +/// \brief Trapdoor Function (TF) Signature Scheme +/// \tparam STANDARD standard +/// \tparam H hash function +/// \tparam KEYS keys used in the signature scheme +/// \tparam ALG_INFO algorithm information +template +class TF_SS; + +template > +class TF_SS : public KEYS +{ +public: + /// see SignatureStandard for a list of standards + typedef STANDARD Standard; + typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod; + typedef TF_SignatureSchemeOptions SchemeOptions; + + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} + + /// implements PK_Signer interface + typedef PK_FinalTemplate > Signer; + /// implements PK_Verifier interface + typedef PK_FinalTemplate > Verifier; +}; + +/// \brief Discrete Log (DL) signature scheme +/// \tparam KEYS keys used in the signature scheme +/// \tparam SA signature algorithm +/// \tparam MEM message encoding method +/// \tparam H hash function +/// \tparam ALG_INFO algorithm information +template +class DL_SS; + +template > +class DL_SS : public KEYS +{ + typedef DL_SignatureSchemeOptions SchemeOptions; + +public: + static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";} + + /// implements PK_Signer interface + typedef PK_FinalTemplate > Signer; + /// implements PK_Verifier interface + typedef PK_FinalTemplate > Verifier; +}; + +/// \brief Discrete Log (DL) encryption scheme +/// \tparam KEYS keys used in the encryption scheme +/// \tparam AA key agreement algorithm +/// \tparam DA key derivation algorithm +/// \tparam EA encryption algorithm +/// \tparam ALG_INFO algorithm information +template +class DL_ES : public KEYS +{ + typedef DL_CryptoSchemeOptions SchemeOptions; + +public: + /// implements PK_Decryptor interface + typedef PK_FinalTemplate > Decryptor; + /// implements PK_Encryptor interface + typedef PK_FinalTemplate > Encryptor; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/pwdbased.h b/third_party/cryptoppwin/include/cryptopp/pwdbased.h new file mode 100644 index 00000000..49cf53c7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/pwdbased.h @@ -0,0 +1,481 @@ +// pwdbased.h - originally written and placed in the public domain by Wei Dai +// Cutover to KeyDerivationFunction interface by Uri Blumenthal +// Marcel Raad and Jeffrey Walton in March 2018. + +/// \file pwdbased.h +/// \brief Password based key derivation functions + +#ifndef CRYPTOPP_PWDBASED_H +#define CRYPTOPP_PWDBASED_H + +#include "cryptlib.h" +#include "hrtimer.h" +#include "integer.h" +#include "argnames.h" +#include "algparam.h" +#include "hmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +// ******************** PBKDF1 ******************** + +/// \brief PBKDF1 from PKCS #5 +/// \tparam T a HashTransformation class +/// \sa PasswordBasedKeyDerivationFunction, PKCS5_PBKDF1 +/// on the Crypto++ wiki +/// \since Crypto++ 2.0 +template +class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction +{ +public: + virtual ~PKCS5_PBKDF1() {} + + static std::string StaticAlgorithmName () { + const std::string name(std::string("PBKDF1(") + + std::string(T::StaticAlgorithmName()) + std::string(")")); + return name; + } + + // KeyDerivationFunction interface + std::string AlgorithmName() const { + return StaticAlgorithmName(); + } + + // KeyDerivationFunction interface + size_t MaxDerivedKeyLength() const { + return static_cast(T::DIGESTSIZE); + } + + // KeyDerivationFunction interface + size_t GetValidDerivedLength(size_t keylength) const; + + // KeyDerivationFunction interface + virtual size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const NameValuePairs& params = g_nullNameValuePairs) const; + + /// \brief Derive a key from a secret seed + /// \param derived the derived output buffer + /// \param derivedLen the size of the derived buffer, in bytes + /// \param purpose a purpose byte + /// \param secret the seed input buffer + /// \param secretLen the size of the secret buffer, in bytes + /// \param salt the salt input buffer + /// \param saltLen the size of the salt buffer, in bytes + /// \param iterations the number of iterations + /// \param timeInSeconds the in seconds + /// \return the number of iterations performed + /// \throw InvalidDerivedKeyLength if derivedLen 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. + /// \details If timeInSeconds is > 0.0 then DeriveKey will run for + /// the specified amount of time. If timeInSeconds is 0.0 then DeriveKey + /// will run for the specified number of iterations. + /// \details PKCS #5 says PBKDF1 should only take 8-byte salts. This implementation + /// allows salts of any length. + size_t DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const; + +protected: + // KeyDerivationFunction interface + const Algorithm & GetAlgorithm() const { + return *this; + } +}; + +template +size_t PKCS5_PBKDF1::GetValidDerivedLength(size_t keylength) const +{ + if (keylength > MaxDerivedKeyLength()) + return MaxDerivedKeyLength(); + return keylength; +} + +template +size_t PKCS5_PBKDF1::DeriveKey(byte *derived, size_t derivedLen, + const byte *secret, size_t secretLen, const NameValuePairs& params) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + + byte purpose = (byte)params.GetIntValueWithDefault("Purpose", 0); + unsigned int iterations = (unsigned int)params.GetIntValueWithDefault("Iterations", 1); + + double timeInSeconds = 0.0f; + (void)params.GetValue("TimeInSeconds", timeInSeconds); + + ConstByteArrayParameter salt; + (void)params.GetValue(Name::Salt(), salt); + + return DeriveKey(derived, derivedLen, purpose, secret, secretLen, salt.begin(), salt.size(), iterations, timeInSeconds); +} + +template +size_t PKCS5_PBKDF1::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0); + CRYPTOPP_UNUSED(purpose); + + ThrowIfInvalidDerivedKeyLength(derivedLen); + + // Business logic + if (!iterations) { iterations = 1; } + + T hash; + hash.Update(secret, secretLen); + hash.Update(salt, saltLen); + + SecByteBlock buffer(hash.DigestSize()); + hash.Final(buffer); + + unsigned int i; + ThreadUserTimer timer; + + if (timeInSeconds) + timer.StartTimer(); + + for (i=1; iPKCS5_PBKDF2_HMAC +/// on the Crypto++ wiki +/// \since Crypto++ 2.0 +template +class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction +{ +public: + virtual ~PKCS5_PBKDF2_HMAC() {} + + static std::string StaticAlgorithmName () { + const std::string name(std::string("PBKDF2_HMAC(") + + std::string(T::StaticAlgorithmName()) + std::string(")")); + return name; + } + + // KeyDerivationFunction interface + std::string AlgorithmName() const { + return StaticAlgorithmName(); + } + + // KeyDerivationFunction interface + // should multiply by T::DIGESTSIZE, but gets overflow that way + size_t MaxDerivedKeyLength() const { + return 0xffffffffU; + } + + // KeyDerivationFunction interface + size_t GetValidDerivedLength(size_t keylength) const; + + // KeyDerivationFunction interface + size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const NameValuePairs& params = g_nullNameValuePairs) const; + + /// \brief Derive a key from a secret seed + /// \param derived the derived output buffer + /// \param derivedLen the size of the derived buffer, in bytes + /// \param purpose a purpose byte + /// \param secret the seed input buffer + /// \param secretLen the size of the secret buffer, in bytes + /// \param salt the salt input buffer + /// \param saltLen the size of the salt buffer, in bytes + /// \param iterations the number of iterations + /// \param timeInSeconds the in seconds + /// \return the number of iterations performed + /// \throw InvalidDerivedKeyLength if derivedLen 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. + /// \details If timeInSeconds is > 0.0 then DeriveKey will run for + /// the specified amount of time. If timeInSeconds is 0.0 then DeriveKey + /// will run for the specified number of iterations. + size_t DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, + const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const; + +protected: + // KeyDerivationFunction interface + const Algorithm & GetAlgorithm() const { + return *this; + } +}; + +template +size_t PKCS5_PBKDF2_HMAC::GetValidDerivedLength(size_t keylength) const +{ + if (keylength > MaxDerivedKeyLength()) + return MaxDerivedKeyLength(); + return keylength; +} + +template +size_t PKCS5_PBKDF2_HMAC::DeriveKey(byte *derived, size_t derivedLen, + const byte *secret, size_t secretLen, const NameValuePairs& params) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + + byte purpose = (byte)params.GetIntValueWithDefault("Purpose", 0); + unsigned int iterations = (unsigned int)params.GetIntValueWithDefault("Iterations", 1); + + double timeInSeconds = 0.0f; + (void)params.GetValue("TimeInSeconds", timeInSeconds); + + ConstByteArrayParameter salt; + (void)params.GetValue(Name::Salt(), salt); + + return DeriveKey(derived, derivedLen, purpose, secret, secretLen, salt.begin(), salt.size(), iterations, timeInSeconds); +} + +template +size_t PKCS5_PBKDF2_HMAC::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0); + CRYPTOPP_UNUSED(purpose); + + ThrowIfInvalidDerivedKeyLength(derivedLen); + + // Business logic + if (!iterations) { iterations = 1; } + + // DigestSize check due to https://github.com/weidai11/cryptopp/issues/855 + HMAC hmac(secret, secretLen); + if (hmac.DigestSize() == 0) + throw InvalidArgument("PKCS5_PBKDF2_HMAC: DigestSize cannot be 0"); + + SecByteBlock buffer(hmac.DigestSize()); + ThreadUserTimer timer; + + unsigned int i=1; + while (derivedLen > 0) + { + hmac.Update(salt, saltLen); + unsigned int j; + for (j=0; j<4; j++) + { + byte b = byte(i >> ((3-j)*8)); + hmac.Update(&b, 1); + } + hmac.Final(buffer); + +#if CRYPTOPP_MSC_VERSION + const size_t segmentLen = STDMIN(derivedLen, buffer.size()); + memcpy_s(derived, segmentLen, buffer, segmentLen); +#else + const size_t segmentLen = STDMIN(derivedLen, buffer.size()); + std::memcpy(derived, buffer, segmentLen); +#endif + + if (timeInSeconds) + { + timeInSeconds = timeInSeconds / ((derivedLen + buffer.size() - 1) / buffer.size()); + timer.StartTimer(); + } + + for (j=1; jPKCS12_PBKDF +/// on the Crypto++ wiki +/// \since Crypto++ 2.0 +template +class PKCS12_PBKDF : public PasswordBasedKeyDerivationFunction +{ +public: + virtual ~PKCS12_PBKDF() {} + + static std::string StaticAlgorithmName () { + const std::string name(std::string("PBKDF_PKCS12(") + + std::string(T::StaticAlgorithmName()) + std::string(")")); + return name; + } + + // KeyDerivationFunction interface + std::string AlgorithmName() const { + return StaticAlgorithmName(); + } + + // TODO - check this + size_t MaxDerivedKeyLength() const { + return static_cast(-1); + } + + // KeyDerivationFunction interface + size_t GetValidDerivedLength(size_t keylength) const; + + // KeyDerivationFunction interface + size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const NameValuePairs& params = g_nullNameValuePairs) const; + + /// \brief Derive a key from a secret seed + /// \param derived the derived output buffer + /// \param derivedLen the size of the derived buffer, in bytes + /// \param purpose a purpose byte + /// \param secret the seed input buffer + /// \param secretLen the size of the secret buffer, in bytes + /// \param salt the salt input buffer + /// \param saltLen the size of the salt buffer, in bytes + /// \param iterations the number of iterations + /// \param timeInSeconds the in seconds + /// \return the number of iterations performed + /// \throw InvalidDerivedKeyLength if derivedLen 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. + /// \details If timeInSeconds is > 0.0 then DeriveKey will run for + /// the specified amount of time. If timeInSeconds is 0.0 then DeriveKey + /// will run for the specified number of iterations. + size_t DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, + const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const; + +protected: + // KeyDerivationFunction interface + const Algorithm & GetAlgorithm() const { + return *this; + } +}; + +template +size_t PKCS12_PBKDF::GetValidDerivedLength(size_t keylength) const +{ + if (keylength > MaxDerivedKeyLength()) + return MaxDerivedKeyLength(); + return keylength; +} + +template +size_t PKCS12_PBKDF::DeriveKey(byte *derived, size_t derivedLen, + const byte *secret, size_t secretLen, const NameValuePairs& params) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + + byte purpose = (byte)params.GetIntValueWithDefault("Purpose", 0); + unsigned int iterations = (unsigned int)params.GetIntValueWithDefault("Iterations", 1); + + double timeInSeconds = 0.0f; + (void)params.GetValue("TimeInSeconds", timeInSeconds); + + // NULL or 0 length salt OK + ConstByteArrayParameter salt; + (void)params.GetValue(Name::Salt(), salt); + + return DeriveKey(derived, derivedLen, purpose, secret, secretLen, salt.begin(), salt.size(), iterations, timeInSeconds); +} + +template +size_t PKCS12_PBKDF::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const +{ + CRYPTOPP_ASSERT(secret /*&& secretLen*/); + CRYPTOPP_ASSERT(derived && derivedLen); + CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength()); + CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0); + + ThrowIfInvalidDerivedKeyLength(derivedLen); + + // Business logic + if (!iterations) { iterations = 1; } + + const size_t v = T::BLOCKSIZE; // v is in bytes rather than bits as in PKCS #12 + const size_t DLen = v, SLen = RoundUpToMultipleOf(saltLen, v); + const size_t PLen = RoundUpToMultipleOf(secretLen, v), ILen = SLen + PLen; + SecByteBlock buffer(DLen + SLen + PLen); + byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S; + + if (D) // GCC analyzer + std::memset(D, purpose, DLen); + + size_t i; + for (i=0; i 0) + { + hash.CalculateDigest(Ai, buffer, buffer.size()); + + if (timeInSeconds) + { + timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size()); + timer.StartTimer(); + } + + for (i=1; iByteQueue +/// on the Crypto++ wiki. +/// \since Crypto++ 2.0 +class CRYPTOPP_DLL ByteQueue : public Bufferless +{ +public: + virtual ~ByteQueue(); + + /// \brief Construct a ByteQueue + /// \param nodeSize the initial node size + /// \details Internally, ByteQueue uses a ByteQueueNode to store bytes, + /// and nodeSize determines the size of the ByteQueueNode. A value + /// of 0 indicates the ByteQueueNode should be automatically sized, + /// which means a value of 256 is used. + ByteQueue(size_t nodeSize=0); + + /// \brief Copy construct a ByteQueue + /// \param copy the other ByteQueue + ByteQueue(const ByteQueue ©); + + // BufferedTransformation + lword MaxRetrievable() const + {return CurrentSize();} + bool AnyRetrievable() const + {return !IsEmpty();} + + void IsolatedInitialize(const NameValuePairs ¶meters); + byte * CreatePutSpace(size_t &size); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + + size_t Get(byte &outByte); + size_t Get(byte *outString, size_t getMax); + + size_t Peek(byte &outByte) const; + size_t Peek(byte *outString, size_t peekMax) 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; + + /// \brief Set node size + /// \param nodeSize the new node size, in bytes + /// \details The default node size is 256. + void SetNodeSize(size_t nodeSize); + + /// \brief Determine data size + /// \return the data size, in bytes + lword CurrentSize() const; + + /// \brief Determine data availability + /// \return true if the ByteQueue has data, false otherwise + bool IsEmpty() const; + + /// \brief Empty the queue + void Clear(); + + /// \brief Insert data in the queue + /// \param inByte a byte to insert + /// \details Unget() inserts a byte at the head of the queue + void Unget(byte inByte); + + /// \brief Insert data in the queue + /// \param inString a byte array to insert + /// \param length the size of the byte array + /// \details Unget() inserts a byte array at the head of the queue + void Unget(const byte *inString, size_t length); + + /// \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 contiguousSize. + /// Spy() returns the size of the first byte array in the list. The + /// entire data may be larger since the queue is a linked list of + /// byte arrays. + const byte * Spy(size_t &contiguousSize) const; + + /// \brief Insert data in the queue + /// \param inString a byte array to insert + /// \param size the length of the byte array + /// \details LazyPut() inserts a byte array at the tail of the queue. + /// The data may not be copied at this point. Rather, the pointer + /// and size to external data are recorded. + /// \details Another call to Put() or LazyPut() will force the data to + /// be copied. When lazy puts are used, the data is copied when + /// FinalizeLazyPut() is called. + /// \sa LazyPutter + void LazyPut(const byte *inString, size_t size); + + /// \brief Insert data in the queue + /// \param inString a byte array to insert + /// \param size the length of the byte array + /// \details LazyPut() inserts a byte array at the tail of the queue. + /// The data may not be copied at this point. Rather, the pointer + /// and size to external data are recorded. + /// \details Another call to Put() or LazyPut() will force the data to + /// be copied. When lazy puts are used, the data is copied when + /// FinalizeLazyPut() is called. + /// \sa LazyPutter + void LazyPutModifiable(byte *inString, size_t size); + + /// \brief Remove data from the queue + /// \param size the length of the data + /// \throw InvalidArgument if there is no lazy data in the queue or if + /// size is larger than the lazy string + /// \details UndoLazyPut() truncates data inserted using LazyPut() by + /// modifying size. + /// \sa LazyPutter + void UndoLazyPut(size_t size); + + /// \brief Insert data in the queue + /// \details FinalizeLazyPut() copies external data inserted using + /// LazyPut() or LazyPutModifiable() into the tail of the queue. + /// \sa LazyPutter + void FinalizeLazyPut(); + + /// \brief Assign contents from another ByteQueue + /// \param rhs the other ByteQueue + /// \return reference to this ByteQueue + ByteQueue & operator=(const ByteQueue &rhs); + + /// \brief Bitwise compare two ByteQueue + /// \param rhs the other ByteQueue + /// \return true if the size and bits are equal, false otherwise + /// \details operator==() walks each ByteQueue comparing bytes in + /// each queue. operator==() is not constant time. + bool operator==(const ByteQueue &rhs) const; + + /// \brief Bitwise compare two ByteQueue + /// \param rhs the other ByteQueue + /// \return true if the size and bits are not equal, false otherwise + /// \details operator!=() is implemented in terms of operator==(). + /// operator==() is not constant time. + bool operator!=(const ByteQueue &rhs) const {return !operator==(rhs);} + + /// \brief Retrieve data from the queue + /// \param index of byte to retrieve + /// \return byte at the specified index + /// \details operator[]() does not perform bounds checking. + byte operator[](lword index) const; + + /// \brief Swap contents with another ByteQueue + /// \param rhs the other ByteQueue + void swap(ByteQueue &rhs); + + /// \brief A ByteQueue iterator + class Walker : public InputRejecting + { + public: + /// \brief Construct a ByteQueue Walker + /// \param queue a ByteQueue + Walker(const ByteQueue &queue) + : m_queue(queue), m_node(NULLPTR), m_position(0), m_offset(0), m_lazyString(NULLPTR), m_lazyLength(0) + {Initialize();} + + lword GetCurrentPosition() {return m_position;} + + lword MaxRetrievable() const + {return m_queue.CurrentSize() - m_position;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + + size_t Get(byte &outByte); + size_t Get(byte *outString, size_t getMax); + + size_t Peek(byte &outByte) const; + size_t Peek(byte *outString, size_t peekMax) 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; + + private: + const ByteQueue &m_queue; + const ByteQueueNode *m_node; + lword m_position; + size_t m_offset; + const byte *m_lazyString; + size_t m_lazyLength; + }; + + friend class Walker; + +protected: + void CleanupUsedNodes(); + void CopyFrom(const ByteQueue ©); + void Destroy(); + +private: + ByteQueueNode *m_head, *m_tail; + byte *m_lazyString; + size_t m_lazyLength; + size_t m_nodeSize; + bool m_lazyStringModifiable; + bool m_autoNodeSize; +}; + +/// \brief Helper class to finalize Puts on ByteQueue +/// \details LazyPutter ensures LazyPut is committed to the ByteQueue +/// in event of exception. During destruction, the LazyPutter class +/// calls FinalizeLazyPut. +class CRYPTOPP_DLL LazyPutter +{ +public: + virtual ~LazyPutter() { + try {m_bq.FinalizeLazyPut();} + catch(const Exception&) {CRYPTOPP_ASSERT(0);} + } + + /// \brief Construct a LazyPutter + /// \param bq the ByteQueue + /// \param inString a byte array to insert + /// \param size the length of the byte array + /// \details LazyPutter ensures LazyPut is committed to the ByteQueue + /// in event of exception. During destruction, the LazyPutter class + /// calls FinalizeLazyPut. + LazyPutter(ByteQueue &bq, const byte *inString, size_t size) + : m_bq(bq) {bq.LazyPut(inString, size);} + +protected: + LazyPutter(ByteQueue &bq) : m_bq(bq) {} + +private: + ByteQueue &m_bq; +}; + +/// \brief Helper class to finalize Puts on ByteQueue +/// \details LazyPutterModifiable ensures LazyPut is committed to the +/// ByteQueue in event of exception. During destruction, the +/// LazyPutterModifiable class calls FinalizeLazyPut. +class LazyPutterModifiable : public LazyPutter +{ +public: + /// \brief Construct a LazyPutterModifiable + /// \param bq the ByteQueue + /// \param inString a byte array to insert + /// \param size the length of the byte array + /// \details LazyPutterModifiable ensures LazyPut is committed to the + /// ByteQueue in event of exception. During destruction, the + /// LazyPutterModifiable class calls FinalizeLazyPut. + LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size) + : LazyPutter(bq) {bq.LazyPutModifiable(inString, size);} +}; + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rabbit.h b/third_party/cryptoppwin/include/cryptopp/rabbit.h new file mode 100644 index 00000000..0103091d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rabbit.h @@ -0,0 +1,112 @@ +// rabbit.h - written and placed in the public domain by Jeffrey Walton +// based on public domain code by Martin Boesgaard, Mette Vesterager, +// Thomas Pedersen, Jesper Christiansen and Ove Scavenius. +// +// The reference materials and source files are available at +// The eSTREAM Project, http://www.ecrypt.eu.org/stream/e2-rabbit.html. + +/// \file rabbit.h +/// \brief Classes for Rabbit stream cipher +/// \sa The +/// eSTREAM Project | Rabbit and +/// Crypto++ Wiki | Rabbit. +/// \since Crypto++ 8.0 + +#ifndef CRYPTOPP_RABBIT_H +#define CRYPTOPP_RABBIT_H + +#include "strciphr.h" +#include "secblock.h" + +// The library does not have a way to describe an optional IV. Rabbit takes +// an optional IV so two classes are offered to bridge the gap. One provides +// Rabbit without an IV and the second provides Rabbit with an IV. + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Rabbit stream cipher information +/// \since Crypto++ 8.0 +struct RabbitInfo : public FixedKeyLength<16, SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "Rabbit"; } +}; + +/// \brief Rabbit stream cipher information +/// \since Crypto++ 8.0 +struct RabbitWithIVInfo : public FixedKeyLength<16, SimpleKeyingInterface::UNIQUE_IV, 8> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RabbitWithIV"; } +}; + +/// \brief Rabbit stream cipher implementation +/// \since Crypto++ 8.0 +class RabbitPolicy : public AdditiveCipherConcretePolicy, public RabbitInfo +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + bool CanOperateKeystream() const { return true; } + bool CipherIsRandomAccess() const { return false; } + +private: + // Master and working states + FixedSizeSecBlock m_mx, m_mc, m_wx, m_wc; + // Workspace + FixedSizeSecBlock m_t; + word32 m_mcy, m_wcy; // carry +}; + +/// \brief Rabbit stream cipher implementation +/// \since Crypto++ 8.0 +class RabbitWithIVPolicy : public AdditiveCipherConcretePolicy, public RabbitWithIVInfo +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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; } + +private: + // Master and working states + FixedSizeSecBlock m_mx, m_mc, m_wx, m_wc; + // Workspace + FixedSizeSecBlock m_t; + word32 m_mcy, m_wcy; // carry +}; + +/// \brief Rabbit stream cipher +/// \details Rabbit is a stream cipher developed by Martin Boesgaard, Mette Vesterager, +/// Thomas Pedersen, Jesper Christiansen and Ove Scavenius. Rabbit is one of the final four +/// Profile 1 (software) ciphers selected for the eSTREAM portfolio. +/// \details Crypto++ provides Rabbit and RabbitWithIV classes. Two classes are necessary +/// because the library lacks the means to describe and manage optional IVs. +/// \sa RabbitWithIV, The +/// eSTREAM Project | Rabbit and +/// Crypto++ Wiki | Rabbit. +/// \since Crypto++ 8.0 +struct Rabbit : public RabbitInfo, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, RabbitInfo> Encryption; + typedef Encryption Decryption; +}; + +/// \brief Rabbit stream cipher +/// \details Rabbit is a stream cipher developed by Martin Boesgaard, Mette Vesterager, +/// Thomas Pedersen, Jesper Christiansen and Ove Scavenius. Rabbit is one of the final four +/// Profile 1 (software) ciphers selected for the eSTREAM portfolio. +/// \details Crypto++ provides Rabbit and RabbitWithIV classes. Two classes are necessary +/// because the library lacks the means to describe and manage optional IVs. +/// \sa Rabbit, The +/// eSTREAM Project | Rabbit and +/// Crypto++ Wiki | Rabbit. +/// \since Crypto++ 8.0 +struct RabbitWithIV : public RabbitWithIVInfo, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, RabbitWithIVInfo> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_RABBIT_H diff --git a/third_party/cryptoppwin/include/cryptopp/rabin.h b/third_party/cryptoppwin/include/cryptopp/rabin.h new file mode 100644 index 00000000..f1271574 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rabin.h @@ -0,0 +1,135 @@ +// rabin.h - originally written and placed in the public domain by Wei Dai + +/// \file rabin.h +/// \brief Classes for Rabin encryption and signature schemes + +#ifndef CRYPTOPP_RABIN_H +#define CRYPTOPP_RABIN_H + +#include "cryptlib.h" +#include "oaep.h" +#include "pssr.h" +#include "integer.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Rabin trapdoor function using the public key +/// \since Crypto++ 2.0 +class RabinFunction : public TrapdoorFunction, public PublicKey +{ + typedef RabinFunction ThisClass; + +public: + + /// \brief Initialize a Rabin public key + /// \param n the modulus + /// \param r element r + /// \param s element s + void Initialize(const Integer &n, const Integer &r, const Integer &s) + {m_n = n; m_r = r; m_s = s;} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return m_n;} + Integer ImageBound() const {return m_n;} + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + const Integer& GetModulus() const {return m_n;} + const Integer& GetQuadraticResidueModPrime1() const {return m_r;} + const Integer& GetQuadraticResidueModPrime2() const {return m_s;} + + void SetModulus(const Integer &n) {m_n = n;} + void SetQuadraticResidueModPrime1(const Integer &r) {m_r = r;} + void SetQuadraticResidueModPrime2(const Integer &s) {m_s = s;} + +protected: + Integer m_n, m_r, m_s; +}; + +/// \brief Rabin trapdoor function using the private key +/// \since Crypto++ 2.0 +class InvertibleRabinFunction : public RabinFunction, public TrapdoorFunctionInverse, public PrivateKey +{ + typedef InvertibleRabinFunction ThisClass; + +public: + + /// \brief Initialize a Rabin private key + /// \param n modulus + /// \param r element r + /// \param s element s + /// \param p first prime factor + /// \param q second prime factor + /// \param u q-1 mod p + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const Integer &n, const Integer &r, const Integer &s, const Integer &p, const Integer &q, const Integer &u) + {m_n = n; m_r = r; m_s = s; m_p = p; m_q = q; m_u = u;} + + /// \brief Create a Rabin private key + /// \param rng a RandomNumberGenerator derived class + /// \param keybits the size of the key, 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. + void Initialize(RandomNumberGenerator &rng, unsigned int keybits) + {GenerateRandomWithKeySize(rng, keybits);} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + /*! parameters: (ModulusSize) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} + +protected: + Integer m_p, m_q, m_u; +}; + +/// \brief Rabin keys +struct Rabin +{ + static std::string StaticAlgorithmName() {return "Rabin-Crypto++Variant";} + typedef RabinFunction PublicKey; + typedef InvertibleRabinFunction PrivateKey; +}; + +/// \brief Rabin encryption scheme +/// \tparam STANDARD encryption standard +template +struct RabinES : public TF_ES +{ +}; + +/// \brief Rabin signature scheme +/// \tparam STANDARD signature standard +/// \tparam H hash transformation +template +struct RabinSS : public TF_SS +{ +}; + +// More typedefs for backwards compatibility +class SHA1; +typedef RabinES >::Decryptor RabinDecryptor; +typedef RabinES >::Encryptor RabinEncryptor; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/randpool.h b/third_party/cryptoppwin/include/cryptopp/randpool.h new file mode 100644 index 00000000..51227c35 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/randpool.h @@ -0,0 +1,104 @@ +// randpool.h - originally written and placed in the public domain by Wei Dai +// OldRandPool added by JW in August, 2017. + +/// \file randpool.h +/// \brief Class file for Randomness Pool +/// \details RandomPool can be used to generate cryptographic quality pseudorandom bytes +/// after seeding the pool with IncorporateEntropy(). Internally, the generator uses +/// AES-256 to produce the stream. Entropy is stirred in using SHA-256. +/// \details RandomPool used to follow the design of randpool in PGP 2.6.x. At version 5.5 +/// RandomPool was redesigned to reduce the risk of reusing random numbers after state +/// rollback (which may occur when running in a virtual machine like VMware or a hosted +/// environment). +/// \details If you need the pre-Crypto++ 5.5 generator then use OldRandomPool class. You +/// should migrate away from OldRandomPool at the earliest opportunity. Use RandomPool +/// or AutoSeededRandomPool instead. +/// \since Crypto++ 4.0 (PGP 2.6.x style), Crypto++ 5.5 (AES-256 based) + +#ifndef CRYPTOPP_RANDPOOL_H +#define CRYPTOPP_RANDPOOL_H + +#include "cryptlib.h" +#include "filters.h" +#include "secblock.h" +#include "smartptr.h" +#include "aes.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Randomness Pool based on AES-256 +/// \details RandomPool can be used to generate cryptographic quality pseudorandom bytes +/// after seeding the pool with IncorporateEntropy(). Internally, the generator uses +/// AES-256 to produce the stream. Entropy is stirred in using SHA-256. +/// \details RandomPool used to follow the design of randpool in PGP 2.6.x. At version 5.5 +/// RandomPool was redesigned to reduce the risk of reusing random numbers after state +/// rollback, which may occur when running in a virtual machine like VMware or a hosted +/// environment. +/// \details You should reseed the generator after a fork() to avoid multiple generators +/// with the same internal state. +/// \details If you need the pre-Crypto++ 5.5 generator then use OldRandomPool class. You +/// should migrate away from OldRandomPool at the earliest opportunity. +/// \sa OldRandomPool +/// \since Crypto++ 4.0 (PGP 2.6.x style), Crypto++ 5.5 (AES-256 based) +class CRYPTOPP_DLL RandomPool : public RandomNumberGenerator, public NotCopyable +{ +public: + /// \brief Construct a RandomPool + RandomPool(); + + bool CanIncorporateEntropy() const {return true;} + void IncorporateEntropy(const byte *input, size_t length); + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); + +private: + FixedSizeAlignedSecBlock m_seed; + FixedSizeAlignedSecBlock m_key; + member_ptr m_pCipher; + bool m_keySet; +}; + +/// \brief Randomness Pool based on PGP 2.6.x with MDC +/// \details If you need the pre-Crypto++ 5.5 generator then use OldRandomPool class. The +/// OldRandomPool also provides the modern interface, including CanIncorporateEntropy, +/// IncorporateEntropy and GenerateIntoBufferedTransformation. +/// \details You should reseed the generator after a fork() to avoid multiple generators +/// with the same internal state. +/// \details You should migrate away from OldRandomPool at the earliest opportunity. Use a +/// modern random number generator or key derivation function, like AutoSeededRandomPool or +/// HKDF. +/// \warning This class uses an old style PGP 2.6.x with MDC. The generator risks reusing +/// random numbers after state rollback. You should migrate away from OldRandomPool at +/// the earliest opportunity. +/// \sa RandomPool, AutoSeededRandomPool, HKDF, P1363_KDF2, PKCS12_PBKDF, PKCS5_PBKDF2_HMAC +/// \since Crypto++ 6.0 +class CRYPTOPP_DLL OldRandomPool : public RandomNumberGenerator +{ +public: + /// \brief Construct an OldRandomPool + /// \param poolSize internal pool size of the generator + /// \details poolSize must be greater than 16 + OldRandomPool(unsigned int poolSize=384); + + // RandomNumberGenerator interface (Crypto++ 5.5 and above) + bool CanIncorporateEntropy() const {return true;} + void IncorporateEntropy(const byte *input, size_t length); + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); + + byte GenerateByte(); + void GenerateBlock(byte *output, size_t size); + + // GenerateWord32 is overridden and provides Crypto++ 5.4 behavior. + // Taken from RandomNumberSource::GenerateWord32 in cryptlib.cpp. + word32 GenerateWord32 (word32 min=0, word32 max=0xffffffffUL); + +protected: + void Stir(); + +private: + SecByteBlock pool, key; + size_t addPos, getPos; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rc2.h b/third_party/cryptoppwin/include/cryptopp/rc2.h new file mode 100644 index 00000000..1b296d27 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rc2.h @@ -0,0 +1,90 @@ +// rc2.h - originally written and placed in the public domain by Wei Dai + +/// \file rc2.h +/// \brief Classes for the RC2 block cipher +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_RC2_H +#define CRYPTOPP_RC2_H + +#include "seckey.h" +#include "secblock.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief RC2 block cipher information +/// \since Crypto++ 3.0 +struct RC2_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 1, 128> +{ + CRYPTOPP_CONSTANT(DEFAULT_EFFECTIVE_KEYLENGTH = 1024); + CRYPTOPP_CONSTANT(MAX_EFFECTIVE_KEYLENGTH = 1024); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RC2";} +}; + +/// \brief RC2 block cipher +/// \sa RC2 on the Crypto Lounge. +/// \since Crypto++ 3.0 +class RC2 : public RC2_Info, public BlockCipherDocumentation +{ + /// \brief Class specific methods used to operate the cipher. + /// \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + protected: + FixedSizeSecBlock K; // expanded key table + }; + + /// \brief Class specific methods used to operate the cipher in the forward direction. + /// \details Implementations and overrides in \p Enc apply to \p ENCRYPTION. + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief Class specific methods used to operate the cipher in the reverse direction. + /// \details Implementations and overrides in \p Dec apply to \p DECRYPTION. + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + + /// \brief Class specific methods used to operate the cipher in the forward direction. + /// \details Implementations and overrides in \p Encryption apply to \p ENCRYPTION. + class Encryption : public BlockCipherFinal + { + public: + Encryption() {} + Encryption(const byte *key, size_t keyLen=DEFAULT_KEYLENGTH) + {SetKey(key, keyLen);} + Encryption(const byte *key, size_t keyLen, int effectiveKeyLen) + {SetKey(key, keyLen, MakeParameters("EffectiveKeyLength", effectiveKeyLen));} + }; + + /// \brief Class specific methods used to operate the cipher in the reverse direction. + /// \details Implementations and overrides in \p Decryption apply to \p DECRYPTION. + class Decryption : public BlockCipherFinal + { + public: + Decryption() {} + Decryption(const byte *key, size_t keyLen=DEFAULT_KEYLENGTH) + {SetKey(key, keyLen);} + Decryption(const byte *key, size_t keyLen, int effectiveKeyLen) + {SetKey(key, keyLen, MakeParameters("EffectiveKeyLength", effectiveKeyLen));} + }; +}; + +typedef RC2::Encryption RC2Encryption; +typedef RC2::Decryption RC2Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rc5.h b/third_party/cryptoppwin/include/cryptopp/rc5.h new file mode 100644 index 00000000..541ffbc0 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rc5.h @@ -0,0 +1,59 @@ +// rc5.h - originally written and placed in the public domain by Wei Dai + +/// \file rc5.h +/// \brief Classes for the RC5 block cipher + +#ifndef CRYPTOPP_RC5_H +#define CRYPTOPP_RC5_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief RC5 block cipher information +/// \since Crypto++ 1.0 +struct RC5_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 0, 255>, public VariableRounds<16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RC5";} + typedef word32 RC5_WORD; +}; + +/// \brief RC5 block cipher +/// \sa RC5 +/// \since Crypto++ 1.0 +class RC5 : public RC5_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + unsigned int r; // number of rounds + SecBlock sTable; // expanded key table + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef RC5::Encryption RC5Encryption; +typedef RC5::Decryption RC5Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rc6.h b/third_party/cryptoppwin/include/cryptopp/rc6.h new file mode 100644 index 00000000..7b80d356 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rc6.h @@ -0,0 +1,60 @@ +// rc6.h - originally written and placed in the public domain by Wei Dai + +/// \file rc6.h +/// \brief Classes for the RC6 block cipher +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_RC6_H +#define CRYPTOPP_RC6_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief RC6 block cipher information +/// \since Crypto++ 3.0 +struct RC6_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8>, public VariableRounds<20> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RC6";} + typedef word32 RC6_WORD; +}; + +/// \brief RC6 block cipher +/// \sa RC6 +/// \since Crypto++ 3.0 +class RC6 : public RC6_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + unsigned int r; // number of rounds + SecBlock sTable; // expanded key table + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef RC6::Encryption RC6Encryption; +typedef RC6::Decryption RC6Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rdrand.h b/third_party/cryptoppwin/include/cryptopp/rdrand.h new file mode 100644 index 00000000..d1f3c412 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rdrand.h @@ -0,0 +1,145 @@ +// rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. + +/// \file rdrand.h +/// \brief Classes for RDRAND and RDSEED +/// \since Crypto++ 5.6.3 + +#ifndef CRYPTOPP_RDRAND_H +#define CRYPTOPP_RDRAND_H + +#include "cryptlib.h" + +// This class file provides both RDRAND and RDSEED. They were added at +// Crypto++ 5.6.3. At compile time, it uses CRYPTOPP_BOOL_{X86|X32|X64} +// to select an implementation or "throw NotImplemented". At runtime the +// constructor will throw RDRAND_Err or RDSEED_Err if a generator is +// is not available. +// The original classes accepted a retry count. Retries were superfluous for +// RDRAND, and RDSEED encountered a failure about 1 in 256 bytes depending +// on the processor. Retries were removed at Crypto++ 6.0 because +// GenerateBlock unconditionally retries and always fulfills the request. + +// Throughput varies wildly depending on processor and manufacturer. A Core i5 or +// Core i7 RDRAND can generate at over 200 MiB/s. It is below theroetical +// maximum, but it takes about 5 instructions to generate, retry and store a +// result. A low-end Celeron may perform RDRAND at about 7 MiB/s. RDSEED +// performs at about 1/4 to 1/2 the rate of RDRAND. AMD RDRAND performed poorly +// during testing with Athlon X4 845. The Bulldozer v4 only performed at 1 MiB/s. + +// Microsoft added RDRAND in August 2012, VS2012; RDSEED in October 2013, VS2013. +// GCC added RDRAND in December 2010, GCC 4.6. LLVM added RDRAND in July 2012, +// Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1. + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Exception thrown when a RDRAND generator encounters +/// a generator related error. +/// \since Crypto++ 5.6.3 +class RDRAND_Err : public Exception +{ +public: + RDRAND_Err(const std::string &operation) + : Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {} +}; + +/// \brief Hardware generated random numbers using RDRAND instruction +/// \sa MaurerRandomnessTest() for random bit generators +/// \since Crypto++ 5.6.3 +class RDRAND : public RandomNumberGenerator +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDRAND"; } + + virtual ~RDRAND() {} + + /// \brief Construct a RDRAND generator + /// \details According to DJ of Intel, the Intel RDRAND circuit does not underflow. + /// If it did hypothetically underflow, then it would return 0 for the random value. + /// AMD's RDRAND implementation appears to provide the same behavior. + /// \throw RDRAND_Err if the random number generator is not available + RDRAND(); + + /// \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 "RDRAND"; + } +}; + +/// \brief Exception thrown when a RDSEED generator encounters +/// a generator related error. +/// \since Crypto++ 5.6.3 +class RDSEED_Err : public Exception +{ +public: + RDSEED_Err(const std::string &operation) + : Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {} +}; + +/// \brief Hardware generated random numbers using RDSEED instruction +/// \sa MaurerRandomnessTest() for random bit generators +/// \since Crypto++ 5.6.3 +class RDSEED : public RandomNumberGenerator +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDSEED"; } + + virtual ~RDSEED() {} + + /// \brief Construct a RDSEED generator + /// \details Empirical testing under a 6th generation i7 (6200U) shows RDSEED fails + /// to fulfill requests at about once every for every 256 bytes requested. + /// The generator runs about 4 times slower than RDRAND. + /// \throw RDSEED_Err if the random number generator is not available + RDSEED(); + + /// \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 "RDSEED"; + } +}; + +NAMESPACE_END + +#endif // CRYPTOPP_RDRAND_H diff --git a/third_party/cryptoppwin/include/cryptopp/resource.h b/third_party/cryptoppwin/include/cryptopp/resource.h new file mode 100644 index 00000000..ae07ae7f --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by cryptopp.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rijndael.h b/third_party/cryptoppwin/include/cryptopp/rijndael.h new file mode 100644 index 00000000..272975aa --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rijndael.h @@ -0,0 +1,109 @@ +// rijndael.h - originally written and placed in the public domain by Wei Dai + +/// \file rijndael.h +/// \brief Classes for Rijndael encryption algorithm +/// \details All key sizes are supported. The library only provides Rijndael with 128-bit blocks, +/// and not 192-bit or 256-bit blocks +/// \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, ARMv7 AES since Crypto++ 8.0 + +#ifndef CRYPTOPP_RIJNDAEL_H +#define CRYPTOPP_RIJNDAEL_H + +#include "seckey.h" +#include "secblock.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_RIJNDAEL_ASM 1 +#endif + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_ARM32 || \ + CRYPTOPP_BOOL_ARMV8 || CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 +# define CRYPTOPP_RIJNDAEL_ADVANCED_PROCESS_BLOCKS 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Rijndael block cipher information +/// \details All key sizes are supported. The library only provides Rijndael with 128-bit blocks, +/// and not 192-bit or 256-bit blocks +/// \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, ARMv7 AES since Crypto++ 8.0 +struct Rijndael_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "AES";} +}; + +/// \brief Rijndael block cipher +/// \details All key sizes are supported. The library only provides Rijndael with 128-bit blocks, +/// and not 192-bit or 256-bit blocks +/// \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, ARMv7 AES since Crypto++ 8.0 +/// \sa Rijndael +class CRYPTOPP_DLL Rijndael : public Rijndael_Info, public BlockCipherDocumentation +{ + /// \brief Rijndael block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + std::string AlgorithmProvider() const; + unsigned int OptimalDataAlignment() const; + + protected: + static void FillEncTable(); + static void FillDecTable(); + + // VS2005 workaround: have to put these on separate lines, or error C2487 is triggered in DLL build + static const byte Se[256]; + static const byte Sd[256]; + + static const word32 rcon[]; + + unsigned int m_rounds; + SecBlock > m_key; + mutable SecByteBlock m_aliasBlock; + }; + + /// \brief Encryption transformation + /// \details Enc provides implementation for encryption transformation. All key sizes are supported. + /// The library only provides Rijndael with 128-bit blocks, and not 192-bit or 256-bit blocks + /// \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, ARMv7 AES since Crypto++ 8.0 + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_RIJNDAEL_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 sizes are supported. + /// The library only provides Rijndael with 128-bit blocks, and not 192-bit or 256-bit blocks + /// \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, ARMv7 AES since Crypto++ 8.0 + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_RIJNDAEL_ADVANCED_PROCESS_BLOCKS + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Rijndael::Encryption RijndaelEncryption; +typedef Rijndael::Decryption RijndaelDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ripemd.h b/third_party/cryptoppwin/include/cryptopp/ripemd.h new file mode 100644 index 00000000..cf700840 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ripemd.h @@ -0,0 +1,65 @@ +// ripemd.h - originally written and placed in the public domain by Wei Dai + +/// \file +/// \brief Classes for RIPEMD message digest + +#ifndef CRYPTOPP_RIPEMD_H +#define CRYPTOPP_RIPEMD_H + +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief RIPEMD-160 message digest +/// \details Digest size is 160-bits. +/// \sa RIPEMD-160 +/// \since Crypto++ 2.1 +class RIPEMD160 : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word32 *digest, const word32 *data); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RIPEMD-160";} +}; + +/// \brief RIPEMD-320 message digest +/// \details Digest size is 320-bits. +/// \sa RIPEMD-320 +/// \since Crypto++ 2.1 +class RIPEMD320 : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word32 *digest, const word32 *data); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RIPEMD-320";} +}; + +/// \brief RIPEMD-128 message digest +/// \details Digest size is 128-bits. +/// \warning RIPEMD-128 is considered insecure, and should not be used unless you absolutely need it for compatibility. +/// \sa RIPEMD-128 +/// \since Crypto++ 2.1 +class RIPEMD128 : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word32 *digest, const word32 *data); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RIPEMD-128";} +}; + +/// \brief RIPEMD-256 message digest +/// \details Digest size is 256-bits. +/// \warning RIPEMD-256 is considered insecure, and should not be used unless you absolutely need it for compatibility. +/// \sa RIPEMD-256 +/// \since Crypto++ 2.1 +class RIPEMD256 : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word32 *digest, const word32 *data); + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RIPEMD-256";} +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rng.h b/third_party/cryptoppwin/include/cryptopp/rng.h new file mode 100644 index 00000000..74456acb --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rng.h @@ -0,0 +1,111 @@ +// rng.h - originally written and placed in the public domain by Wei Dai + +/// \file rng.h +/// \brief Miscellaneous classes for RNGs +/// \details This file contains miscellaneous classes for RNGs, including LC_RNG(), +/// X917RNG() and MaurerRandomnessTest() +/// \sa osrng.h, randpool.h + +#ifndef CRYPTOPP_RNG_H +#define CRYPTOPP_RNG_H + +#include "cryptlib.h" +#include "filters.h" +#include "smartptr.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Linear Congruential Generator (LCG) +/// \details Originally propsed by William S. England. +/// \warning LC_RNG is suitable for simulations, where uniformaly distributed numbers are +/// required quickly. It should not be used for cryptographic purposes. +class LC_RNG : public RandomNumberGenerator +{ +public: + /// \brief Construct a Linear Congruential Generator (LCG) + /// \param init_seed the initial value for the generator + LC_RNG(word32 init_seed) + : seed(init_seed) {} + + void GenerateBlock(byte *output, size_t size); + + word32 GetSeed() {return seed;} + +private: + word32 seed; + + static const word32 m; + static const word32 q; + static const word16 a; + static const word16 r; +}; + +/// \brief ANSI X9.17 RNG +/// \details X917RNG is from ANSI X9.17 Appendix C, and it uses a 64-bit block cipher, like TripleDES. +/// If you use a 128-bit block cipher, like AES, then you are effectively using an ANSI X9.31 generator. +/// \details You should reseed the generator after a fork() to avoid multiple generators +/// with the same internal state. +/// \sa AutoSeededX917RNG, DefaultAutoSeededRNG +class CRYPTOPP_DLL X917RNG : public RandomNumberGenerator, public NotCopyable +{ +public: + /// \brief Construct a X917RNG + /// \param cipher the block cipher to use for the generator + /// \param seed a byte buffer to use as a seed + /// \param deterministicTimeVector additional entropy + /// \details cipher will be deleted by the destructor. seed must be at least + /// BlockSize() in length. deterministicTimeVector = 0 means obtain time vector + /// from the system. + /// \details When constructing a X917RNG, the generator must be keyed or an access + /// violation will occur because the time vector is encrypted using the block cipher. + /// To key the generator during constructions, perform the following: + ///
+	///  SecByteBlock key(AES::DEFAULT_KEYLENGTH), seed(AES::BLOCKSIZE);
+	///  OS_GenerateRandomBlock(false, key, key.size());
+	///  OS_GenerateRandomBlock(false, seed, seed.size());
+	///  X917RNG prng(new AES::Encryption(key, AES::DEFAULT_KEYLENGTH), seed, NULLPTR);
+ /// \sa AutoSeededX917RNG + X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector = NULLPTR); + + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); + +private: + member_ptr m_cipher; + const unsigned int m_size; // S, blocksize of cipher + SecByteBlock m_datetime; // DT, buffer for enciphered timestamp + SecByteBlock m_randseed, m_lastBlock, m_deterministicTimeVector; +}; + +/// \brief Maurer's Universal Statistical Test for Random Bit Generators +/// \details This class implements Maurer's Universal Statistical Test for +/// Random Bit Generators. It is intended for measuring the randomness of +/// *PHYSICAL* RNGs. +/// \details For more details see Maurer's paper in Journal of Cryptology, 1992. +class MaurerRandomnessTest : public Bufferless +{ +public: + /// \brief Construct a MaurerRandomnessTest + MaurerRandomnessTest(); + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + + /// \brief Provides the number of bytes of input is needed by the test + /// \return how many more bytes of input is needed by the test + // BytesNeeded() returns how many more bytes of input is needed by the test + // GetTestValue() should not be called before BytesNeeded()==0 + unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;} + + // returns a number between 0.0 and 1.0, describing the quality of the + // random numbers entered + double GetTestValue() const; + +private: + enum {L=8, V=256, Q=2000, K=2000}; + double sum; + unsigned int n; + unsigned int tab[V]; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rsa.h b/third_party/cryptoppwin/include/cryptopp/rsa.h new file mode 100644 index 00000000..1d45fb6e --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rsa.h @@ -0,0 +1,288 @@ +// rsa.h - originally written and placed in the public domain by Wei Dai + +/// \file rsa.h +/// \brief Classes for the RSA cryptosystem +/// \details This file contains classes that implement the RSA +/// ciphers and signature schemes as defined in PKCS #1 v2.0. + +#ifndef CRYPTOPP_RSA_H +#define CRYPTOPP_RSA_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "integer.h" +#include "pkcspad.h" +#include "oaep.h" +#include "emsa2.h" +#include "asn.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief RSA trapdoor function using the public key +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL RSAFunction : public TrapdoorFunction, public X509PublicKey +{ + typedef RSAFunction ThisClass; + +public: + /// \brief Initialize a RSA public key + /// \param n the modulus + /// \param e the public exponent + void Initialize(const Integer &n, const Integer &e) + {m_n = n; m_e = e;} + + // X509PublicKey + OID GetAlgorithmID() const; + void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePublicKey(BufferedTransformation &bt) const; + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // TrapdoorFunction + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return m_n;} + Integer ImageBound() const {return m_n;} + + // non-derived + const Integer & GetModulus() const {return m_n;} + const Integer & GetPublicExponent() const {return m_e;} + + void SetModulus(const Integer &n) {m_n = n;} + void SetPublicExponent(const Integer &e) {m_e = e;} + +protected: + Integer m_n, m_e; +}; + +/// \brief RSA trapdoor function using the private key +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey +{ + typedef InvertibleRSAFunction ThisClass; + +public: + /// \brief Create a RSA private key + /// \param rng a RandomNumberGenerator derived class + /// \param modulusBits the size of the modulus, in bits + /// \param e the desired public exponent + /// \details Initialize() creates a new keypair using a public exponent of 17. + /// \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. + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &e = 17); + + /// \brief Initialize a RSA private key + /// \param n modulus + /// \param e public exponent + /// \param d private exponent + /// \param p first prime factor + /// \param q second prime factor + /// \param dp d mod p + /// \param dq d mod q + /// \param u q-1 mod p + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const Integer &n, const Integer &e, const Integer &d, const Integer &p, const Integer &q, const Integer &dp, const Integer &dq, const Integer &u) + {m_n = n; m_e = e; m_d = d; m_p = p; m_q = q; m_dp = dp; m_dq = dq; m_u = u;} + + /// \brief Initialize a RSA private key + /// \param n modulus + /// \param e public exponent + /// \param d private exponent + /// \details This Initialize() function overload initializes a private key from existing parameters. + /// Initialize() will factor n using d and populate {p,q,dp,dq,u}. + void Initialize(const Integer &n, const Integer &e, const Integer &d); + + // PKCS8PrivateKey + void BERDecode(BufferedTransformation &bt) + {PKCS8PrivateKey::BERDecode(bt);} + void DEREncode(BufferedTransformation &bt) const + {PKCS8PrivateKey::DEREncode(bt);} + void Load(BufferedTransformation &bt) + {PKCS8PrivateKey::BERDecode(bt);} + void Save(BufferedTransformation &bt) const + {PKCS8PrivateKey::DEREncode(bt);} + OID GetAlgorithmID() const {return RSAFunction::GetAlgorithmID();} + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; + + // TrapdoorFunctionInverse + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + + // GeneratableCryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + // parameters: (ModulusSize, PublicExponent (default 17)) + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // non-derived interface + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + const Integer& GetPrivateExponent() const {return m_d;} + const Integer& GetModPrime1PrivateExponent() const {return m_dp;} + const Integer& GetModPrime2PrivateExponent() const {return m_dq;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + void SetPrivateExponent(const Integer &d) {m_d = d;} + void SetModPrime1PrivateExponent(const Integer &dp) {m_dp = dp;} + void SetModPrime2PrivateExponent(const Integer &dq) {m_dq = dq;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} + +protected: + Integer m_d, m_p, m_q, m_dp, m_dq, m_u; +}; + +/// \brief RSA trapdoor function using the public key +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL RSAFunction_ISO : public RSAFunction +{ +public: + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return ++(m_n>>1);} +}; + +/// \brief RSA trapdoor function using the private key +/// \since Crypto++ 1.0 +class CRYPTOPP_DLL InvertibleRSAFunction_ISO : public InvertibleRSAFunction +{ +public: + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + Integer PreimageBound() const {return ++(m_n>>1);} +}; + +/// \brief RSA algorithm +/// \since Crypto++ 1.0 +struct CRYPTOPP_DLL RSA +{ + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "RSA";} + typedef RSAFunction PublicKey; + typedef InvertibleRSAFunction PrivateKey; +}; + +/// \brief RSA encryption algorithm +/// \tparam STANDARD signature standard +/// \sa RSA cryptosystem +/// \since Crypto++ 1.0 +template +struct RSAES : public TF_ES +{ +}; + +/// \brief RSA signature algorithm +/// \tparam STANDARD signature standard +/// \tparam H hash transformation +/// \details See documentation of PKCS1v15 for a list of hash functions that can be used with it. +/// \sa RSA signature scheme with appendix +/// \since Crypto++ 1.0 +template +struct RSASS : public TF_SS +{ +}; + +/// \brief RSA algorithm +/// \since Crypto++ 1.0 +struct CRYPTOPP_DLL RSA_ISO +{ + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "RSA-ISO";} + typedef RSAFunction_ISO PublicKey; + typedef InvertibleRSAFunction_ISO PrivateKey; +}; + +/// \brief RSA signature algorithm +/// \tparam H hash transformation +/// \since Crypto++ 1.0 +template +struct RSASS_ISO : public TF_SS +{ +}; + +/// \brief \ref RSAES "RSAES::Decryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +DOCUMENTED_TYPEDEF(RSAES::Decryptor, RSAES_PKCS1v15_Decryptor); +/// \brief \ref RSAES "RSAES::Encryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +DOCUMENTED_TYPEDEF(RSAES::Encryptor, RSAES_PKCS1v15_Encryptor); + +/// \brief \ref RSAES "RSAES>::Decryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +DOCUMENTED_TYPEDEF(RSAES >::Decryptor, RSAES_OAEP_SHA_Decryptor); +/// \brief \ref RSAES "RSAES>::Encryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +DOCUMENTED_TYPEDEF(RSAES >::Encryptor, RSAES_OAEP_SHA_Encryptor); + +/// \brief \ref RSAES "RSAES>::Decryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +/// \since Crypto++ 8.8 +DOCUMENTED_TYPEDEF(RSAES >::Decryptor, RSAES_OAEP_SHA256_Decryptor); +/// \brief \ref RSAES "RSAES>::Encryptor" typedef +/// \details RSA encryption scheme defined in PKCS #1 v2.0 +/// \since Crypto++ 8.8 +DOCUMENTED_TYPEDEF(RSAES >::Encryptor, RSAES_OAEP_SHA256_Encryptor); + +#ifdef CRYPTOPP_DOXYGEN_PROCESSING +/// \brief \ref RSASS "RSASS::Signer" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +class RSASSA_PKCS1v15_SHA_Signer : public RSASS::Signer {}; +/// \brief \ref RSASS "RSASS::Verifier" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +class RSASSA_PKCS1v15_SHA_Verifier : public RSASS::Verifier {}; + +/// \brief \ref RSASS "RSASS::Signer" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 8.8 +class RSASSA_PKCS1v15_SHA256_Signer : public RSASS::Signer {}; +/// \brief \ref RSASS "RSASS::Verifier" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 8.8 +class RSASSA_PKCS1v15_SHA256_Verifier : public RSASS::Verifier {}; + +namespace Weak { + +/// \brief \ref RSASS "RSASS::Signer" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +class RSASSA_PKCS1v15_MD2_Signer : public RSASS::Signer {}; +/// \brief \ref RSASS "RSASS::Verifier" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +class RSASSA_PKCS1v15_MD2_Verifier : public RSASS::Verifier {}; + +/// \brief \ref RSASS "RSASS::Signer" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +class RSASSA_PKCS1v15_MD5_Signer : public RSASS::Signer {}; +/// \brief \ref RSASS "RSASS::Verifier" typedef +/// \details RSA signature schemes defined in PKCS #1 v2.0 +/// \since Crypto++ 1.0 +class RSASSA_PKCS1v15_MD5_Verifier : public RSASS::Verifier {}; +} + +#else +typedef RSASS::Signer RSASSA_PKCS1v15_SHA_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_SHA_Verifier; + +typedef RSASS::Signer RSASSA_PKCS1v15_SHA256_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_SHA256_Verifier; + +namespace Weak { + typedef RSASS::Signer RSASSA_PKCS1v15_MD2_Signer; + typedef RSASS::Verifier RSASSA_PKCS1v15_MD2_Verifier; + typedef RSASS::Signer RSASSA_PKCS1v15_MD5_Signer; + typedef RSASS::Verifier RSASSA_PKCS1v15_MD5_Verifier; +} +#endif // CRYPTOPP_DOXYGEN_PROCESSING + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/rw.h b/third_party/cryptoppwin/include/cryptopp/rw.h new file mode 100644 index 00000000..ca2cd30a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/rw.h @@ -0,0 +1,146 @@ +// rw.h - originally written and placed in the public domain by Wei Dai + +/// \file rw.h +/// \brief Classes for Rabin-Williams signature scheme +/// \details The implementation provides Rabin-Williams signature schemes as defined in +/// IEEE P1363. It uses Bernstein's tweaked square roots in place of square roots to +/// speedup calculations. +/// \sa RSA signatures and Rabin–Williams +/// signatures: the state of the art (20080131), Section 6, The tweaks e and f. +/// \since Crypto++ 3.0 + +#ifndef CRYPTOPP_RW_H +#define CRYPTOPP_RW_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "integer.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Rabin-Williams trapdoor function using the public key +/// \since Crypto++ 3.0, Tweaked roots using e and f since Crypto++ 5.6.4 +class CRYPTOPP_DLL RWFunction : public TrapdoorFunction, public PublicKey +{ + typedef RWFunction ThisClass; + +public: + + /// \brief Initialize a Rabin-Williams public key + /// \param n the modulus + void Initialize(const Integer &n) + {m_n = n;} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + void Save(BufferedTransformation &bt) const + {DEREncode(bt);} + void Load(BufferedTransformation &bt) + {BERDecode(bt);} + + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return ++(m_n>>1);} + Integer ImageBound() const {return m_n;} + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + const Integer& GetModulus() const {return m_n;} + void SetModulus(const Integer &n) {m_n = n;} + +protected: + Integer m_n; +}; + +/// \brief Rabin-Williams trapdoor function using the private key +/// \since Crypto++ 3.0, Tweaked roots using e and f since Crypto++ 5.6.4 +class CRYPTOPP_DLL InvertibleRWFunction : public RWFunction, public TrapdoorFunctionInverse, public PrivateKey +{ + typedef InvertibleRWFunction ThisClass; + +public: + /// \brief Construct an InvertibleRWFunction + InvertibleRWFunction() : m_precompute(false) {} + + /// \brief Initialize a Rabin-Williams private key + /// \param n modulus + /// \param p first prime factor + /// \param q second prime factor + /// \param u q-1 mod p + /// \details This Initialize() function overload initializes a private key from existing parameters. + void Initialize(const Integer &n, const Integer &p, const Integer &q, const Integer &u); + + /// \brief Create a Rabin-Williams private key + /// \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. + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) + {GenerateRandomWithKeySize(rng, modulusBits);} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + void Save(BufferedTransformation &bt) const + {DEREncode(bt);} + void Load(BufferedTransformation &bt) + {BERDecode(bt);} + + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + + // GeneratibleCryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + /*! parameters: (ModulusSize) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} + + virtual bool SupportsPrecomputation() const {return true;} + virtual void Precompute(unsigned int unused = 0) {CRYPTOPP_UNUSED(unused); PrecomputeTweakedRoots();} + virtual void Precompute(unsigned int unused = 0) const {CRYPTOPP_UNUSED(unused); PrecomputeTweakedRoots();} + + virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation); + virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const; + +protected: + void PrecomputeTweakedRoots() const; + +protected: + Integer m_p, m_q, m_u; + + mutable Integer m_pre_2_9p, m_pre_2_3q, m_pre_q_p; + mutable bool m_precompute; +}; + +/// \brief Rabin-Williams keys +/// \since Crypto++ 3.0 +struct RW +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "RW";} + typedef RWFunction PublicKey; + typedef InvertibleRWFunction PrivateKey; +}; + +/// \brief Rabin-Williams signature scheme +/// \tparam STANDARD signature standard +/// \tparam H hash transformation +/// \since Crypto++ 3.0 +template +struct RWSS : public TF_SS +{ +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/safer.h b/third_party/cryptoppwin/include/cryptopp/safer.h new file mode 100644 index 00000000..dacd8c3f --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/safer.h @@ -0,0 +1,98 @@ +// safer.h - originally written and placed in the public domain by Wei Dai + +/// \file safer.h +/// \brief Classes for the SAFER and SAFER-K block ciphers + +#ifndef CRYPTOPP_SAFER_H +#define CRYPTOPP_SAFER_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SAFER block cipher +class SAFER +{ +public: + /// \brief SAFER block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public BlockCipher + { + public: + unsigned int OptimalDataAlignment() const {return 1;} + void UncheckedSetKey(const byte *userkey, unsigned int length, const NameValuePairs ¶ms); + + protected: + virtual bool Strengthened() const =0; + + SecByteBlock keySchedule; + static const byte exp_tab[256]; + static const byte log_tab[256]; + }; + + /// \brief SAFER block cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief SAFER block cipher decryption operation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; +}; + +/// \brief SAFER block cipher default implementation +/// \tparam BASE SAFER::Enc or SAFER::Dec derived base class +/// \tparam INFO SAFER_Info derived class +/// \tparam STR flag indicating a strengthened implementation +/// \details SAFER-K is not strengthened; while SAFER-SK is strengthened. +template +class CRYPTOPP_NO_VTABLE SAFER_Impl : public BlockCipherImpl +{ +protected: + bool Strengthened() const {return STR;} +}; + +/// \brief SAFER-K block cipher information +struct SAFER_K_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 8, 16, 8>, public VariableRounds<10, 1, 13> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SAFER-K";} +}; + +/// \brief SAFER-K block cipher +/// \sa SAFER-K +class SAFER_K : public SAFER_K_Info, public SAFER, public BlockCipherDocumentation +{ +public: + typedef BlockCipherFinal > Encryption; + typedef BlockCipherFinal > Decryption; +}; + +/// \brief SAFER-SK block cipher information +struct SAFER_SK_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 8, 16, 8>, public VariableRounds<10, 1, 13> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SAFER-SK";} +}; + +/// \brief SAFER-SK block cipher +/// \sa SAFER-SK +class SAFER_SK : public SAFER_SK_Info, public SAFER, public BlockCipherDocumentation +{ +public: + typedef BlockCipherFinal > Encryption; + typedef BlockCipherFinal > Decryption; +}; + +typedef SAFER_K::Encryption SAFER_K_Encryption; +typedef SAFER_K::Decryption SAFER_K_Decryption; + +typedef SAFER_SK::Encryption SAFER_SK_Encryption; +typedef SAFER_SK::Decryption SAFER_SK_Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/salsa.h b/third_party/cryptoppwin/include/cryptopp/salsa.h new file mode 100644 index 00000000..40df15d8 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/salsa.h @@ -0,0 +1,104 @@ +// salsa.h - originally written and placed in the public domain by Wei Dai + +/// \file salsa.h +/// \brief Classes for Salsa and Salsa20 stream ciphers + +#ifndef CRYPTOPP_SALSA_H +#define CRYPTOPP_SALSA_H + +#include "strciphr.h" +#include "secblock.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_SALSA_ASM 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Salsa20 core transform +/// \param data the data to transform +/// \param rounds the number of rounds +/// \details Several algorithms, like CryptoBox and Scrypt, require access to +/// the core Salsa20 transform. The current Crypto++ implementation does not +/// lend itself to disgorging the Salsa20 cipher from the Salsa20 core transform. +/// Instead Salsa20_Core is provided with customary accelerations. +void Salsa20_Core(word32* data, unsigned int rounds); + +/// \brief Salsa20 stream cipher information +/// \since Crypto++ 5.4 +struct Salsa20_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8> +{ + static std::string StaticAlgorithmName() {return "Salsa20";} +}; + +/// \brief Salsa20 stream cipher operation +/// \since Crypto++ 5.4 +class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy +{ +protected: + Salsa20_Policy() : m_rounds(ROUNDS) {} + void CipherSetKey(const NameValuePairs ¶ms, 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); + +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + unsigned int GetAlignment() const; + unsigned int GetOptimalBlockSize() const; +#endif + + std::string AlgorithmProvider() const; + + CRYPTOPP_CONSTANT(ROUNDS = 20); // Default rounds + FixedSizeAlignedSecBlock m_state; + int m_rounds; +}; + +/// \brief Salsa20 stream cipher +/// \details Salsa20 provides a variable number of rounds: 8, 12 or 20. The default number of rounds is 20. +/// \sa The Salsa20 +/// family of stream ciphers (20071225), +/// Snuffle 2005: the Salsa20 encryption +/// function and Salsa20 +/// \since Crypto++ 5.4 +struct Salsa20 : public Salsa20_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, Salsa20_Info> Encryption; + typedef Encryption Decryption; +}; + +/// \brief XSalsa20 stream cipher information +/// \since Crypto++ 5.4 +struct XSalsa20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24> +{ + static std::string StaticAlgorithmName() {return "XSalsa20";} +}; + +/// \brief XSalsa20 stream cipher operation +/// \since Crypto++ 5.4 +class CRYPTOPP_NO_VTABLE XSalsa20_Policy : public Salsa20_Policy +{ +public: + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); + +protected: + FixedSizeSecBlock m_key; +}; + +/// \brief XSalsa20 stream cipher +/// \details XSalsa20 provides a variable number of rounds: 8, 12 or 20. The default number of rounds is 20. +/// \sa XSalsa20 +/// \since Crypto++ 5.4 +struct XSalsa20 : public XSalsa20_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, XSalsa20_Info> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/scrypt.h b/third_party/cryptoppwin/include/cryptopp/scrypt.h new file mode 100644 index 00000000..a275e993 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/scrypt.h @@ -0,0 +1,103 @@ +// scrypt.h - written and placed in public domain by Jeffrey Walton. +// Based on reference source code by Colin Percival. + +/// \file scrypt.h +/// \brief Classes for Scrypt from RFC 7914 +/// \sa Stronger Key Derivation via +/// Sequential Memory-Hard Functions, +/// The scrypt key derivation function +/// and RFC 7914, The scrypt Password-Based +/// Key Derivation Function +/// \since Crypto++ 7.0 + +#ifndef CRYPTOPP_SCRYPT_H +#define CRYPTOPP_SCRYPT_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Scrypt key derivation function +/// \details The Crypto++ implementation uses OpenMP to accelerate the derivation when +/// available. +/// \details The Crypto++ implementation of Scrypt is limited by C++ datatypes. For +/// example, the library is limited to a derived key length of SIZE_MAX, +/// and not (2^32 - 1) * 32. +/// \sa Stronger Key Derivation via +/// Sequential Memory-Hard Functions, +/// The scrypt key derivation function +/// and RFC 7914, The scrypt Password-Based +/// Key Derivation Function +/// \since Crypto++ 7.0 +class Scrypt : public KeyDerivationFunction +{ +public: + virtual ~Scrypt() {} + + static std::string StaticAlgorithmName () { + return "scrypt"; + } + + // KeyDerivationFunction interface + std::string AlgorithmName() const { + return StaticAlgorithmName(); + } + + // KeyDerivationFunction interface + size_t MaxDerivedKeyLength() const { + return static_cast(0)-1; + } + + // KeyDerivationFunction interface + size_t GetValidDerivedLength(size_t keylength) const; + + // KeyDerivationFunction interface + size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const NameValuePairs& params) const; + + /// \brief Derive a key from a seed + /// \param derived the derived output buffer + /// \param derivedLen the size of the derived buffer, in bytes + /// \param secret the seed input buffer + /// \param secretLen the size of the secret buffer, in bytes + /// \param salt the salt input buffer + /// \param saltLen the size of the salt buffer, in bytes + /// \param cost the CPU/memory cost factor + /// \param blockSize the block size + /// \param parallelization the parallelization factor + /// \return the number of iterations performed + /// \throw InvalidDerivedKeyLength if derivedLen 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. + /// \details The CPU/Memory cost parameter ("N" in the documents) must be + /// larger than 1, a power of 2, and less than 2^(128 * r / 8). + /// \details The parameter blockSize ("r" in the documents) specifies the block + /// size. + /// \details The parallelization parameter ("p" in the documents) is a positive + /// integer less than or equal to ((2^32-1) * 32) / (128 * r). Due to Microsoft + /// and its OpenMP 2.0 implementation parallelization is limited to + /// std::numeric_limits::max(). + /// \details Scrypt always returns 1 because it only performs 1 iteration. Other + /// derivation functions, like PBKDF's, will return more interesting values. + /// \details The Crypto++ implementation of Scrypt is limited by C++ datatypes. For + /// example, the library is limited to a derived key length of SIZE_MAX, + /// and not (2^32 - 1) * 32. + size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, + const byte *salt, size_t saltLen, word64 cost=2, word64 blockSize=8, word64 parallelization=1) const; + +protected: + enum {defaultCost=2, defaultBlockSize=8, defaultParallelization=1}; + + // KeyDerivationFunction interface + const Algorithm & GetAlgorithm() const { + return *this; + } + + inline void ValidateParameters(size_t derivedlen, word64 cost, word64 blockSize, word64 parallelization) const; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_SCRYPT_H diff --git a/third_party/cryptoppwin/include/cryptopp/seal.h b/third_party/cryptoppwin/include/cryptopp/seal.h new file mode 100644 index 00000000..750df966 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/seal.h @@ -0,0 +1,59 @@ +// seal.h - originally written and placed in the public domain by Wei Dai + +/// \file seal.h +/// \brief Classes for SEAL stream cipher +/// \since Crypto++ 2.2 + +#ifndef CRYPTOPP_SEAL_H +#define CRYPTOPP_SEAL_H + +#include "strciphr.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SEAL stream cipher information +/// \tparam B Endianness of the stream cipher +/// \since Crypto++ 2.2 +template +struct SEAL_Info : public FixedKeyLength<20, SimpleKeyingInterface::INTERNALLY_GENERATED_IV, 4> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == LITTLE_ENDIAN_ORDER ? "SEAL-3.0-LE" : "SEAL-3.0-BE";} +}; + +/// \brief SEAL stream cipher operation +/// \tparam B Endianness of the stream cipher +/// \since Crypto++ 2.2 +template +class CRYPTOPP_NO_VTABLE SEAL_Policy : public AdditiveCipherConcretePolicy, public SEAL_Info +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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); + +private: + FixedSizeSecBlock m_T; + FixedSizeSecBlock m_S; + SecBlock m_R; + + word32 m_startCount, m_iterationsPerCount; + word32 m_outsideCounter, m_insideCounter; +}; + +/// \brief SEAL stream cipher +/// \tparam B Endianness of the stream cipher +/// \sa SEAL +/// \since Crypto++ 2.2 +template +struct SEAL : public SEAL_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, SEAL_Info > Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/secblock.h b/third_party/cryptoppwin/include/cryptopp/secblock.h new file mode 100644 index 00000000..1f200125 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/secblock.h @@ -0,0 +1,1310 @@ +// secblock.h - originally written and placed in the public domain by Wei Dai + +/// \file secblock.h +/// \brief Classes and functions for secure memory allocations. + +#ifndef CRYPTOPP_SECBLOCK_H +#define CRYPTOPP_SECBLOCK_H + +#include "config.h" +#include "allocate.h" +#include "misc.h" +#include "stdcpp.h" + +#if defined(CRYPTOPP_MSC_VERSION) +# pragma warning(push) +# pragma warning(disable: 4231 4275 4700) +# if (CRYPTOPP_MSC_VERSION >= 1400) +# pragma warning(disable: 6011 6386 28193) +# endif +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** secure memory allocation *************** + +/// \brief Base class for all allocators used by SecBlock +/// \tparam T the class or type +template +class AllocatorBase +{ +public: + typedef T value_type; + typedef size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef T & reference; + typedef const T & const_reference; + + pointer address(reference r) const {return (&r);} + const_pointer address(const_reference r) const {return (&r); } + void construct(pointer p, const T& val) {new (p) T(val);} + void destroy(pointer p) {CRYPTOPP_UNUSED(p); p->~T();} + + /// \brief Returns the maximum number of elements the allocator can provide + /// \details ELEMS_MAX is the maximum number of elements the + /// Allocator can provide. The value of ELEMS_MAX is + /// SIZE_MAX/sizeof(T). std::numeric_limits was avoided + /// due to lack of constexpr-ness in C++03 and below. + /// \note In C++03 and below ELEMS_MAX is a static data member of type + /// size_type. In C++11 and above ELEMS_MAX is an enum + /// inheriting from size_type. In both cases ELEMS_MAX can be + /// used before objects are fully constructed, and it does not suffer the + /// limitations of class methods like max_size. + /// \sa Issue 346/CVE-2016-9939 + /// \since Crypto++ 6.0 +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) + static const size_type ELEMS_MAX = ...; +#elif defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_MSC_VERSION <= 1400) + static const size_type ELEMS_MAX = (~(size_type)0)/sizeof(T); +#elif defined(CRYPTOPP_CXX11_STRONG_ENUM) + enum : size_type {ELEMS_MAX = SIZE_MAX/sizeof(T)}; +#else + static const size_type ELEMS_MAX = SIZE_MAX/sizeof(T); +#endif + + /// \brief Returns the maximum number of elements the allocator can provide + /// \return the maximum number of elements the allocator can provide + /// \details Internally, preprocessor macros are used rather than std::numeric_limits + /// because the latter is not a constexpr. Some compilers, like Clang, do not + /// optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear + /// to optimize it well in either form. + CRYPTOPP_CONSTEXPR size_type max_size() const {return ELEMS_MAX;} + +#if defined(__SUNPRO_CC) + // https://github.com/weidai11/cryptopp/issues/770 + // and https://stackoverflow.com/q/53999461/608639 + CRYPTOPP_CONSTEXPR size_type max_size(size_type n) const {return SIZE_MAX/n;} +#endif + +#if defined(CRYPTOPP_CXX11_VARIADIC_TEMPLATES) || defined(CRYPTOPP_DOXYGEN_PROCESSING) + + /// \brief Constructs a new V using variadic arguments + /// \tparam V the type to be forwarded + /// \tparam Args the arguments to be forwarded + /// \param ptr pointer to type V + /// \param args variadic arguments + /// \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES + /// is defined. The define is controlled by compiler versions detected in config.h. + template + void construct(V* ptr, Args&&... args) {::new ((void*)ptr) V(std::forward(args)...);} + + /// \brief Destroys an V constructed with variadic arguments + /// \tparam V the type to be forwarded + /// \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES + /// is defined. The define is controlled by compiler versions detected in config.h. + template + void destroy(V* ptr) {if (ptr) ptr->~V();} + +#endif + +protected: + + /// \brief Verifies the allocator can satisfy a request based on size + /// \param size the size of the allocation, in elements + /// \throw InvalidArgument + /// \details CheckSize verifies the number of elements requested is valid. + /// \details If size is greater than max_size(), then InvalidArgument is thrown. + /// The library throws InvalidArgument if the size is too large to satisfy. + /// \details Internally, preprocessor macros are used rather than std::numeric_limits + /// because the latter is not a constexpr. Some compilers, like Clang, do not + /// optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear + /// to optimize it well in either form. + /// \details The sizeof(T) != 1 in the condition attempts to help the + /// compiler optimize the check for byte types. Coverity findings for + /// CONSTANT_EXPRESSION_RESULT were generated without it. For byte types, + /// size never exceeded ELEMS_MAX but the code was not removed. + /// \note size is the count of elements, and not the number of bytes + static void CheckSize(size_t size) + { + // Squash MSC C4100 warning for size. Also see commit 42b7c4ea5673. + CRYPTOPP_UNUSED(size); + // C++ throws std::bad_alloc (C++03) or std::bad_array_new_length (C++11) here. + if (sizeof(T) != 1 && size > ELEMS_MAX) + throw InvalidArgument("AllocatorBase: requested size would cause integer overflow"); + } +}; + +#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T_type) \ + typedef typename AllocatorBase::value_type value_type;\ + typedef typename AllocatorBase::size_type size_type;\ + typedef typename AllocatorBase::difference_type difference_type;\ + typedef typename AllocatorBase::pointer pointer;\ + typedef typename AllocatorBase::const_pointer const_pointer;\ + typedef typename AllocatorBase::reference reference;\ + typedef typename AllocatorBase::const_reference const_reference; + +/// \brief Reallocation function +/// \tparam T the class or type +/// \tparam A the class or type's allocator +/// \param alloc the allocator +/// \param oldPtr the previous allocation +/// \param oldSize the size of the previous allocation +/// \param newSize the new, requested size +/// \param preserve flag that indicates if the old allocation should be preserved +/// \note oldSize and newSize are the count of elements, and not the +/// number of bytes. +template +typename A::pointer StandardReallocate(A& alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) +{ + // Avoid assert on pointer in reallocate. SecBlock regularly uses NULL + // pointers rather returning non-NULL 0-sized pointers. + if (oldSize == newSize) + return oldPtr; + + if (preserve) + { + typename A::pointer newPtr = alloc.allocate(newSize, NULLPTR); + const typename A::size_type copySize = STDMIN(oldSize, newSize) * sizeof(T); + + if (oldPtr && newPtr) + memcpy_s(newPtr, copySize, oldPtr, copySize); + + if (oldPtr) + alloc.deallocate(oldPtr, oldSize); + + return newPtr; + } + else + { + if (oldPtr) + alloc.deallocate(oldPtr, oldSize); + + return alloc.allocate(newSize, NULLPTR); + } +} + +/// \brief Allocates a block of memory with cleanup +/// \tparam T class or type +/// \tparam T_Align16 boolean that determines whether allocations should be aligned on a 16-byte boundary +/// \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate() +/// for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls +/// UnalignedAllocate() for memory allocations. +/// \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors +/// CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter. +template +class AllocatorWithCleanup : public AllocatorBase +{ +public: + CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T) + + /// \brief Allocates a block of memory + /// \param ptr the size of the allocation + /// \param size the size of the allocation, in elements + /// \return a memory block + /// \throw InvalidArgument + /// \details allocate() first checks the size of the request. If it is non-0 + /// and less than max_size(), then an attempt is made to fulfill the request + /// using either AlignedAllocate() or UnalignedAllocate(). AlignedAllocate() is + /// used if T_Align16 is true. UnalignedAllocate() used if T_Align16 is false. + /// \details This is the C++ *Placement New* operator. ptr is not used, and the + /// function asserts in Debug builds if ptr is non-NULL. + /// \sa CallNewHandler() for the methods used to recover from a failed + /// allocation attempt. + /// \note size is the count of elements, and not the number of bytes + pointer allocate(size_type size, const void *ptr = NULLPTR) + { + CRYPTOPP_UNUSED(ptr); CRYPTOPP_ASSERT(ptr == NULLPTR); + this->CheckSize(size); + if (size == 0) + return NULLPTR; + +#if CRYPTOPP_BOOL_ALIGN16 + if (T_Align16) + return reinterpret_cast(AlignedAllocate(size*sizeof(T))); +#endif + + return reinterpret_cast(UnalignedAllocate(size*sizeof(T))); + } + + /// \brief Deallocates a block of memory + /// \param ptr the pointer for the allocation + /// \param size the size of the allocation, in elements + /// \details Internally, SecureWipeArray() is called before deallocating the + /// memory. Once the memory block is wiped or zeroized, AlignedDeallocate() + /// or UnalignedDeallocate() is called. + /// \details AlignedDeallocate() is used if T_Align16 is true. + /// UnalignedDeallocate() used if T_Align16 is false. + void deallocate(void *ptr, size_type size) + { + // Avoid assert on pointer in deallocate. SecBlock regularly uses NULL + // pointers rather returning non-NULL 0-sized pointers. + if (ptr) + { + SecureWipeArray(reinterpret_cast(ptr), size); + +#if CRYPTOPP_BOOL_ALIGN16 + if (T_Align16) + return AlignedDeallocate(ptr); +#endif + + UnalignedDeallocate(ptr); + } + } + + /// \brief Reallocates a block of memory + /// \param oldPtr the previous allocation + /// \param oldSize the size of the previous allocation + /// \param newSize the new, requested size + /// \param preserve flag that indicates if the old allocation should be preserved + /// \return pointer to the new memory block + /// \details Internally, reallocate() calls StandardReallocate(). + /// \details If preserve is true, then index 0 is used to begin copying the + /// old memory block to the new one. If the block grows, then the old array + /// is copied in its entirety. If the block shrinks, then only newSize + /// elements are copied from the old block to the new one. + /// \note oldSize and newSize are the count of elements, and not the + /// number of bytes. + pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve) + { + CRYPTOPP_ASSERT((oldPtr && oldSize) || !(oldPtr || oldSize)); + return StandardReallocate(*this, oldPtr, oldSize, newSize, preserve); + } + + /// \brief Template class member Rebind + /// \tparam V bound class or type + /// \details Rebind allows a container class to allocate a different type of object + /// to store elements. For example, a std::list will allocate std::list_node to + /// store elements in the list. + /// \details VS.NET STL enforces the policy of "All STL-compliant allocators + /// have to provide a template class member called rebind". + template struct rebind { typedef AllocatorWithCleanup other; }; +#if (CRYPTOPP_MSC_VERSION >= 1500) + AllocatorWithCleanup() {} + template AllocatorWithCleanup(const AllocatorWithCleanup &) {} +#endif +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +#if defined(CRYPTOPP_WORD128_AVAILABLE) +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; // for Integer +#endif +#if CRYPTOPP_BOOL_X86 +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; // for Integer +#endif + +/// \brief NULL allocator +/// \tparam T class or type +/// \details A NullAllocator is useful for fixed-size, stack based allocations +/// (i.e., static arrays used by FixedSizeAllocatorWithCleanup). +/// \details A NullAllocator always returns 0 for max_size(), and always returns +/// NULL for allocation requests. Though the allocator does not allocate at +/// runtime, it does perform a secure wipe or zeroization during cleanup. +template +class NullAllocator : public AllocatorBase +{ +public: + //LCOV_EXCL_START + CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T) + + // TODO: should this return NULL or throw bad_alloc? Non-Windows C++ standard + // libraries always throw. And late mode Windows throws. Early model Windows + // (circa VC++ 6.0) returned NULL. + pointer allocate(size_type n, const void* unused = NULLPTR) + { + CRYPTOPP_UNUSED(n); CRYPTOPP_UNUSED(unused); + CRYPTOPP_ASSERT(false); return NULLPTR; + } + + void deallocate(void *p, size_type n) + { + CRYPTOPP_UNUSED(p); CRYPTOPP_UNUSED(n); + CRYPTOPP_ASSERT(false); + } + + CRYPTOPP_CONSTEXPR size_type max_size() const {return 0;} + //LCOV_EXCL_STOP +}; + +/// \brief Static secure memory block with cleanup +/// \tparam T class or type +/// \tparam S fixed-size of the stack-based memory block, in elements +/// \tparam T_Align16 boolean that determines whether allocations should +/// be aligned on a 16-byte boundary +/// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- +/// based allocation at compile time. The class can grow its memory +/// block at runtime if a suitable allocator is available. If size +/// grows beyond S and a suitable allocator is available, then the +/// statically allocated array is obsoleted. +/// \note This allocator can't be used with standard collections because +/// they require that all objects of the same allocator type are equivalent. +template , bool T_Align16 = false> +class FixedSizeAllocatorWithCleanup : public AllocatorBase +{ + // The body of FixedSizeAllocatorWithCleanup is provided in the two + // partial specializations that follow. The two specializations + // pivot on the boolean template parameter T_Align16. +}; + +/// \brief Static secure memory block with cleanup +/// \tparam T class or type +/// \tparam S fixed-size of the stack-based memory block, in elements +/// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- +/// based allocation at compile time. The class can grow its memory +/// block at runtime if a suitable allocator is available. If size +/// grows beyond S and a suitable allocator is available, then the +/// statically allocated array is obsoleted. +/// \note This allocator can't be used with standard collections because +/// they require that all objects of the same allocator type are equivalent. +template +class FixedSizeAllocatorWithCleanup : public AllocatorBase +{ +public: + CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T) + + /// \brief Constructs a FixedSizeAllocatorWithCleanup + FixedSizeAllocatorWithCleanup() : m_allocated(false) {} + + /// \brief Allocates a block of memory + /// \param size the count elements in the memory block + /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-based + /// allocation at compile time. If size is less than or equal to + /// S, then a pointer to the static array is returned. + /// \details The class can grow its memory block at runtime if a suitable + /// allocator is available. If size grows beyond S and a suitable + /// allocator is available, then the statically allocated array is + /// obsoleted. If a suitable allocator is not available, as with a + /// NullAllocator, then the function returns NULL and a runtime error + /// eventually occurs. + /// \sa reallocate(), SecBlockWithHint + pointer allocate(size_type size) + { + CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8)); + + if (size <= S && !m_allocated) + { + m_allocated = true; + return GetAlignedArray(); + } + else + return m_fallbackAllocator.allocate(size); + } + + /// \brief Allocates a block of memory + /// \param size the count elements in the memory block + /// \param hint an unused hint + /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- + /// based allocation at compile time. If size is less than or equal to + /// S, then a pointer to the static array is returned. + /// \details The class can grow its memory block at runtime if a suitable + /// allocator is available. If size grows beyond S and a suitable + /// allocator is available, then the statically allocated array is + /// obsoleted. If a suitable allocator is not available, as with a + /// NullAllocator, then the function returns NULL and a runtime error + /// eventually occurs. + /// \sa reallocate(), SecBlockWithHint + pointer allocate(size_type size, const void *hint) + { + CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8)); + + if (size <= S && !m_allocated) + { + m_allocated = true; + return GetAlignedArray(); + } + else + return m_fallbackAllocator.allocate(size, hint); + } + + /// \brief Deallocates a block of memory + /// \param ptr a pointer to the memory block to deallocate + /// \param size the count elements in the memory block + /// \details The memory block is wiped or zeroized before deallocation. + /// If the statically allocated memory block is active, then no + /// additional actions are taken after the wipe. + /// \details If a dynamic memory block is active, then the pointer and + /// size are passed to the allocator for deallocation. + void deallocate(void *ptr, size_type size) + { + // Avoid assert on pointer in deallocate. SecBlock regularly uses NULL + // pointers rather returning non-NULL 0-sized pointers. + if (ptr == GetAlignedArray()) + { + // If the m_allocated assert fires then the bit twiddling for + // GetAlignedArray() is probably incorrect for the platform. + // Be sure to check CRYPTOPP_ALIGN_DATA(8). The platform may + // not have a way to declaratively align data to 8. + CRYPTOPP_ASSERT(size <= S); + CRYPTOPP_ASSERT(m_allocated); + m_allocated = false; + SecureWipeArray(reinterpret_cast(ptr), size); + } + else + { + if (ptr) + m_fallbackAllocator.deallocate(ptr, size); + } + } + + /// \brief Reallocates a block of memory + /// \param oldPtr the previous allocation + /// \param oldSize the size of the previous allocation + /// \param newSize the new, requested size + /// \param preserve flag that indicates if the old allocation should + /// be preserved + /// \return pointer to the new memory block + /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- + /// based allocation at compile time. If size is less than or equal to + /// S, then a pointer to the static array is returned. + /// \details The class can grow its memory block at runtime if a suitable + /// allocator is available. If size grows beyond S and a suitable + /// allocator is available, then the statically allocated array is + /// obsoleted. If a suitable allocator is not available, as with a + /// NullAllocator, then the function returns NULL and a runtime error + /// eventually occurs. + /// \note size is the count of elements, and not the number of bytes. + /// \sa reallocate(), SecBlockWithHint + pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve) + { + if (oldPtr == GetAlignedArray() && newSize <= S) + { + CRYPTOPP_ASSERT(oldSize <= S); + if (oldSize > newSize) + SecureWipeArray(oldPtr+newSize, oldSize-newSize); + return oldPtr; + } + + pointer newPtr = allocate(newSize, NULLPTR); + if (preserve && newSize) + { + const size_type copySize = STDMIN(oldSize, newSize); + if (newPtr && oldPtr) // GCC analyzer warning + memcpy_s(newPtr, sizeof(T)*newSize, oldPtr, sizeof(T)*copySize); + } + deallocate(oldPtr, oldSize); + return newPtr; + } + + CRYPTOPP_CONSTEXPR size_type max_size() const + { + return STDMAX(m_fallbackAllocator.max_size(), S); + } + +private: + +#if CRYPTOPP_BOOL_ALIGN16 + + // There be demons here... We cannot use CRYPTOPP_ALIGN_DATA(16) + // because linkers on 32-bit machines and some 64-bit machines + // align the stack to 8-bytes or less, and not 16-bytes as + // requested. We can only count on a smaller alignment. All + // toolchains tested appear to honor CRYPTOPP_ALIGN_DATA(8). Also + // see http://stackoverflow.com/a/1468656/608639. + // + // The 16-byte alignment is achieved by padding the requested + // size with extra elements so we have at least 8-bytes of slack + // to work with. Then the array pointer is moved to achieve a + // 16-byte alignment. + // + // The additional 8-bytes introduces a small secondary issue. + // The secondary issue is, a large T results in 0 = 8/sizeof(T). + // The library is OK but users may hit it. So we need to guard + // for a large T, and that is what the enum and PAD achieves. + T* GetAlignedArray() { + + // m_array is aligned on 8 byte boundaries due to + // CRYPTOPP_ALIGN_DATA(8). If m_array%16 is 0, then the buffer + // is 16-byte aligned and nothing needs to be done. if + // m_array%16 is 8, then the buffer is not 16-byte aligned and + // we need to add 8. 8 has that nice symmetric property. + // + // If we needed to use CRYPTOPP_ALIGN_DATA(4) due to toolchain + // limitations, then the calculation would be slightly more + // costly: ptr = m_array + (16 - (m_array % 16)) % 16; + CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8)); + int off = reinterpret_cast(m_array) % 16; + byte* ptr = reinterpret_cast(m_array) + off; + + // Verify the 16-byte alignment. This is the point + // of these extra gyrations. + CRYPTOPP_ASSERT(IsAlignedOn(ptr, 16)); + // Verify the lower bound. This is Issue 982/988. + CRYPTOPP_ASSERT( + reinterpret_cast(ptr) >= + reinterpret_cast(m_array) + ); + // Verify the upper bound. Allocated array with + // pad is large enough. + CRYPTOPP_ASSERT( + reinterpret_cast(ptr+S*sizeof(T)) <= + reinterpret_cast(m_array+(S+PAD)) + ); + + // void* to silence Clang warnings + return reinterpret_cast( + static_cast(ptr) + ); + } + + // PAD is elements, not bytes, and rounded up to ensure no overflow. + enum { Q = sizeof(T), PAD = (Q >= 8) ? 1 : (Q >= 4) ? 2 : (Q >= 2) ? 4 : 8 }; + // enum { Q = sizeof(T), PAD = (Q >= 16) ? 1 : (Q >= 8) ? 2 : (Q >= 4) ? 4 : (Q >= 2) ? 8 : 16 }; + CRYPTOPP_ALIGN_DATA(8) T m_array[S+PAD]; + +#else + + // CRYPTOPP_BOOL_ALIGN16 is 0. If we are here then the user + // probably compiled with CRYPTOPP_DISABLE_ASM. Normally we + // would use the natural alignment of T. The problem we are + // having is, some toolchains are changing the boundary for + // 64-bit arrays. 64-bit elements require 8-byte alignment, + // but the toolchain is laying the array out on a 4 byte + // boundary. See GH #992 for mystery alignment, + // https://github.com/weidai11/cryptopp/issues/992 + T* GetAlignedArray() {return m_array;} + CRYPTOPP_ALIGN_DATA(8) T m_array[S]; + +#endif + + A m_fallbackAllocator; + bool m_allocated; +}; + +/// \brief Static secure memory block with cleanup +/// \tparam T class or type +/// \tparam S fixed-size of the stack-based memory block, in elements +/// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- +/// based allocation at compile time. The class can grow its memory +/// block at runtime if a suitable allocator is available. If size +/// grows beyond S and a suitable allocator is available, then the +/// statically allocated array is obsoleted. +/// \note This allocator can't be used with standard collections because +/// they require that all objects of the same allocator type are equivalent. +template +class FixedSizeAllocatorWithCleanup : public AllocatorBase +{ +public: + CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T) + + /// \brief Constructs a FixedSizeAllocatorWithCleanup + FixedSizeAllocatorWithCleanup() : m_allocated(false) {} + + /// \brief Allocates a block of memory + /// \param size the count elements in the memory block + /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-based + /// allocation at compile time. If size is less than or equal to + /// S, then a pointer to the static array is returned. + /// \details The class can grow its memory block at runtime if a suitable + /// allocator is available. If size grows beyond S and a suitable + /// allocator is available, then the statically allocated array is + /// obsoleted. If a suitable allocator is not available, as with a + /// NullAllocator, then the function returns NULL and a runtime error + /// eventually occurs. + /// \sa reallocate(), SecBlockWithHint + pointer allocate(size_type size) + { + CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8)); + + if (size <= S && !m_allocated) + { + m_allocated = true; + return GetAlignedArray(); + } + else + return m_fallbackAllocator.allocate(size); + } + + /// \brief Allocates a block of memory + /// \param size the count elements in the memory block + /// \param hint an unused hint + /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- + /// based allocation at compile time. If size is less than or equal to + /// S, then a pointer to the static array is returned. + /// \details The class can grow its memory block at runtime if a suitable + /// allocator is available. If size grows beyond S and a suitable + /// allocator is available, then the statically allocated array is + /// obsoleted. If a suitable allocator is not available, as with a + /// NullAllocator, then the function returns NULL and a runtime error + /// eventually occurs. + /// \sa reallocate(), SecBlockWithHint + pointer allocate(size_type size, const void *hint) + { + if (size <= S && !m_allocated) + { + m_allocated = true; + return GetAlignedArray(); + } + else + return m_fallbackAllocator.allocate(size, hint); + } + + /// \brief Deallocates a block of memory + /// \param ptr a pointer to the memory block to deallocate + /// \param size the count elements in the memory block + /// \details The memory block is wiped or zeroized before deallocation. + /// If the statically allocated memory block is active, then no + /// additional actions are taken after the wipe. + /// \details If a dynamic memory block is active, then the pointer and + /// size are passed to the allocator for deallocation. + void deallocate(void *ptr, size_type size) + { + // Avoid assert on pointer in deallocate. SecBlock regularly uses NULL + // pointers rather returning non-NULL 0-sized pointers. + if (ptr == GetAlignedArray()) + { + // If the m_allocated assert fires then + // something overwrote the flag. + CRYPTOPP_ASSERT(size <= S); + CRYPTOPP_ASSERT(m_allocated); + m_allocated = false; + SecureWipeArray((pointer)ptr, size); + } + else + { + if (ptr) + m_fallbackAllocator.deallocate(ptr, size); + m_allocated = false; + } + } + + /// \brief Reallocates a block of memory + /// \param oldPtr the previous allocation + /// \param oldSize the size of the previous allocation + /// \param newSize the new, requested size + /// \param preserve flag that indicates if the old allocation should + /// be preserved + /// \return pointer to the new memory block + /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- + /// based allocation at compile time. If size is less than or equal to + /// S, then a pointer to the static array is returned. + /// \details The class can grow its memory block at runtime if a suitable + /// allocator is available. If size grows beyond S and a suitable + /// allocator is available, then the statically allocated array is + /// obsoleted. If a suitable allocator is not available, as with a + /// NullAllocator, then the function returns NULL and a runtime error + /// eventually occurs. + /// \note size is the count of elements, and not the number of bytes. + /// \sa reallocate(), SecBlockWithHint + pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve) + { + if (oldPtr == GetAlignedArray() && newSize <= S) + { + CRYPTOPP_ASSERT(oldSize <= S); + if (oldSize > newSize) + SecureWipeArray(oldPtr+newSize, oldSize-newSize); + return oldPtr; + } + + pointer newPtr = allocate(newSize, NULLPTR); + if (preserve && newSize) + { + const size_type copySize = STDMIN(oldSize, newSize); + if (newPtr && oldPtr) // GCC analyzer warning + memcpy_s(newPtr, sizeof(T)*newSize, oldPtr, sizeof(T)*copySize); + } + deallocate(oldPtr, oldSize); + return newPtr; + } + + CRYPTOPP_CONSTEXPR size_type max_size() const + { + return STDMAX(m_fallbackAllocator.max_size(), S); + } + +private: + + // T_Align16 is false. Normally we would use the natural + // alignment of T. The problem we are having is, some toolchains + // are changing the boundary for 64-bit arrays. 64-bit elements + // require 8-byte alignment, but the toolchain is laying the array + // out on a 4 byte boundary. See GH #992 for mystery alignment, + // https://github.com/weidai11/cryptopp/issues/992 + T* GetAlignedArray() {return m_array;} + CRYPTOPP_ALIGN_DATA(8) T m_array[S]; + + A m_fallbackAllocator; + bool m_allocated; +}; + +/// \brief Secure memory block with allocator and cleanup +/// \tparam T a class or type +/// \tparam A AllocatorWithCleanup derived class for allocation and cleanup +/// \sa SecBlock +/// on the Crypto++ wiki. +/// \since Crypto++ 2.0 +template > +class SecBlock +{ +public: + typedef typename A::value_type value_type; + typedef typename A::pointer iterator; + typedef typename A::const_pointer const_iterator; + typedef typename A::size_type size_type; + + /// \brief Returns the maximum number of elements the block can hold + /// \details ELEMS_MAX is the maximum number of elements the + /// SecBlock can hold. The value of ELEMS_MAX is + /// SIZE_MAX/sizeof(T). std::numeric_limits was avoided + /// due to lack of constexpr-ness in C++03 and below. + /// \note In C++03 and below ELEMS_MAX is a static data member of type + /// size_type. In C++11 and above ELEMS_MAX is an enum + /// inheriting from size_type. In both cases ELEMS_MAX can be + /// used before objects are fully constructed, and it does not suffer the + /// limitations of class methods like max_size. + /// \sa Issue 346/CVE-2016-9939 + /// \since Crypto++ 6.0 +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) + static const size_type ELEMS_MAX = ...; +#elif defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_MSC_VERSION <= 1400) + static const size_type ELEMS_MAX = (~(size_type)0)/sizeof(T); +#elif defined(CRYPTOPP_CXX11_STRONG_ENUM) + enum : size_type {ELEMS_MAX = A::ELEMS_MAX}; +#else + static const size_type ELEMS_MAX = SIZE_MAX/sizeof(T); +#endif + + /// \brief Construct a SecBlock with space for size elements. + /// \param size the size of the allocation, in elements + /// \throw std::bad_alloc + /// \details The elements are not initialized. + /// \since Crypto++ 2.0 + /// \note size is the count of elements, and not the number of bytes + explicit SecBlock(size_type size=0) + : m_mark(ELEMS_MAX), m_size(size), m_ptr(m_alloc.allocate(size, NULLPTR)) { } + + /// \brief Copy construct a SecBlock from another SecBlock + /// \param t the other SecBlock + /// \throw std::bad_alloc + /// \since Crypto++ 2.0 + SecBlock(const SecBlock &t) + : m_mark(t.m_mark), m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULLPTR)) { + CRYPTOPP_ASSERT((!t.m_ptr && !m_size) || (t.m_ptr && m_size)); + if (m_ptr && t.m_ptr) + memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); + } + + /// \brief Construct a SecBlock from an array of elements. + /// \param ptr a pointer to an array of T + /// \param len the number of elements in the memory block + /// \throw std::bad_alloc + /// \details If ptr!=NULL and len!=0, then the block is initialized from the pointer + /// ptr. If ptr==NULL and len!=0, then the block is initialized to 0. + /// Otherwise, the block is empty and not initialized. + /// \since Crypto++ 2.0 + /// \note size is the count of elements, and not the number of bytes + SecBlock(const T *ptr, size_type len) + : m_mark(ELEMS_MAX), m_size(len), m_ptr(m_alloc.allocate(len, NULLPTR)) { + CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size)); + if (m_ptr && ptr) + memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T)); + else if (m_ptr && m_size) + std::memset(m_ptr, 0, m_size*sizeof(T)); + } + + ~SecBlock() + {m_alloc.deallocate(m_ptr, STDMIN(m_size, m_mark));} + +#ifdef __BORLANDC__ + /// \brief Cast operator + /// \return block pointer cast to non-const T * + /// \since Crypto++ 2.0 + operator T *() const + {return (T*)m_ptr;} +#else + /// \brief Cast operator + /// \return block pointer cast to const void * + /// \since Crypto++ 2.0 + operator const void *() const + {return m_ptr;} + + /// \brief Cast operator + /// \return block pointer cast to non-const void * + /// \since Crypto++ 2.0 + operator void *() + {return m_ptr;} + + /// \brief Cast operator + /// \return block pointer cast to const T * + /// \since Crypto++ 2.0 + operator const T *() const + {return m_ptr;} + + /// \brief Cast operator + /// \return block pointer cast to non-const T * + /// \since Crypto++ 2.0 + operator T *() + {return m_ptr;} +#endif + + /// \brief Provides an iterator pointing to the first element in the memory block + /// \return iterator pointing to the first element in the memory block + /// \since Crypto++ 2.0 + iterator begin() + {return m_ptr;} + /// \brief Provides a constant iterator pointing to the first element in the memory block + /// \return constant iterator pointing to the first element in the memory block + /// \since Crypto++ 2.0 + const_iterator begin() const + {return m_ptr;} + /// \brief Provides an iterator pointing beyond the last element in the memory block + /// \return iterator pointing beyond the last element in the memory block + /// \since Crypto++ 2.0 + iterator end() + {return m_ptr+m_size;} + /// \brief Provides a constant iterator pointing beyond the last element in the memory block + /// \return constant iterator pointing beyond the last element in the memory block + /// \since Crypto++ 2.0 + const_iterator end() const + {return m_ptr+m_size;} + + /// \brief Provides a pointer to the first element in the memory block + /// \return pointer to the first element in the memory block + /// \since Crypto++ 2.0 + typename A::pointer data() {return m_ptr;} + /// \brief Provides a pointer to the first element in the memory block + /// \return constant pointer to the first element in the memory block + /// \since Crypto++ 2.0 + typename A::const_pointer data() const {return m_ptr;} + + /// \brief Provides the count of elements in the SecBlock + /// \return number of elements in the memory block + /// \note the return value is the count of elements, and not the number of bytes + /// \since Crypto++ 2.0 + size_type size() const {return m_size;} + /// \brief Determines if the SecBlock is empty + /// \return true if number of elements in the memory block is 0, false otherwise + /// \since Crypto++ 2.0 + bool empty() const {return m_size == 0;} + + /// \brief Provides a byte pointer to the first element in the memory block + /// \return byte pointer to the first element in the memory block + /// \since Crypto++ 2.0 + byte * BytePtr() {return (byte *)m_ptr;} + /// \brief Return a byte pointer to the first element in the memory block + /// \return constant byte pointer to the first element in the memory block + /// \since Crypto++ 2.0 + const byte * BytePtr() const {return (const byte *)m_ptr;} + /// \brief Provides the number of bytes in the SecBlock + /// \return the number of bytes in the memory block + /// \note the return value is the number of bytes, and not count of elements. + /// \since Crypto++ 2.0 + size_type SizeInBytes() const {return m_size*sizeof(T);} + + /// \brief Set contents and size from an array + /// \param ptr a pointer to an array of T + /// \param len the number of elements in the memory block + /// \details The array pointed to by ptr must be distinct + /// from this SecBlock because Assign() calls New() and then std::memcpy(). + /// The call to New() will invalidate all pointers and iterators, like + /// the pointer returned from data(). + /// \details If the memory block is reduced in size, then the reclaimed + /// memory is set to 0. If an assignment occurs, then Assign() resets + /// the element count after the previous block is zeroized. + /// \since Crypto++ 2.0 + void Assign(const T *ptr, size_type len) + { + New(len); + if (m_ptr && ptr) // GCC analyzer warning + memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T)); + m_mark = ELEMS_MAX; + } + + /// \brief Set contents from a value + /// \param count the number of values to copy + /// \param value the value, repeated count times + /// \details If the memory block is reduced in size, then the reclaimed + /// memory is set to 0. If an assignment occurs, then Assign() resets + /// the element count after the previous block is zeroized. + /// \since Crypto++ 6.0 + void Assign(size_type count, T value) + { + New(count); + for (size_t i=0; i &t) + { + if (this != &t) + { + New(t.m_size); + if (m_ptr && t.m_ptr) // GCC analyzer warning + memcpy_s(m_ptr, m_size*sizeof(T), t, t.m_size*sizeof(T)); + } + m_mark = ELEMS_MAX; + } + + /// \brief Append contents from an array + /// \param ptr a pointer to an array of T + /// \param len the number of elements in the memory block + /// \throw InvalidArgument if resulting size would overflow + /// \details The array pointed to by ptr must be distinct + /// from this SecBlock because Append() calls Grow() and then std::memcpy(). + /// The call to Grow() will invalidate all pointers and iterators, like + /// the pointer returned from data(). + /// \details Append() may be less efficient than a ByteQueue because + /// Append() must Grow() the internal array and then copy elements. + /// The ByteQueue can copy elements without growing. + /// \sa ByteQueue + /// \since Crypto++ 8.6 + void Append(const T *ptr, size_type len) + { + if (ELEMS_MAX - m_size < len) + throw InvalidArgument("SecBlock: buffer overflow"); + + const size_type oldSize = m_size; + Grow(m_size+len); + if (m_ptr && ptr) // GCC analyzer warning + memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), ptr, len*sizeof(T)); + m_mark = ELEMS_MAX; + } + + /// \brief Append contents from another SecBlock + /// \param t the other SecBlock + /// \throw InvalidArgument if resulting size would overflow + /// \details Internally, this SecBlock calls Grow() and then appends t. + /// \details Append() may be less efficient than a ByteQueue because + /// Append() must Grow() the internal array and then copy elements. + /// The ByteQueue can copy elements without growing. + /// \sa ByteQueue + /// \since Crypto++ 8.6 + void Append(const SecBlock &t) + { + if (ELEMS_MAX - m_size < t.m_size) + throw InvalidArgument("SecBlock: buffer overflow"); + + const size_type oldSize = m_size; + if (this != &t) // s += t + { + Grow(m_size+t.m_size); + if (m_ptr && t.m_ptr) // GCC analyzer warning + memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); + } + else // t += t + { + Grow(m_size*2); + if (m_ptr) // GCC analyzer warning + memmove_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), m_ptr, oldSize*sizeof(T)); + } + m_mark = ELEMS_MAX; + } + + /// \brief Append contents from a value + /// \param count the number of values to copy + /// \param value the value, repeated count times + /// \throw InvalidArgument if resulting size would overflow + /// \details Internally, this SecBlock calls Grow() and then appends value. + /// \details Append() may be less efficient than a ByteQueue because + /// Append() must Grow() the internal array and then copy elements. + /// The ByteQueue can copy elements without growing. + /// \sa ByteQueue + /// \since Crypto++ 8.6 + void Append(size_type count, T value) + { + if (ELEMS_MAX - m_size < count) + throw InvalidArgument("SecBlock: buffer overflow"); + + const size_type oldSize = m_size; + Grow(m_size+count); + for (size_t i=oldSize; icount controls the number of + /// elements zeroized, which can be less than size or 0. + /// \details An internal variable, m_mark, is initialized to the maximum number + /// of elements. The maximum number of elements is ELEMS_MAX. Deallocation + /// triggers a zeroization, and the number of elements zeroized is + /// STDMIN(m_size, m_mark). After zeroization, the memory is returned to the + /// system. + /// \details The ASN.1 decoder uses SetMark() to set the element count to 0 + /// before throwing an exception. In this case, the attacker provides a large + /// BER encoded length (say 64MB) but only a small number of content octets + /// (say 16). If the allocator zeroized all 64MB, then a transient DoS could + /// occur as CPU cycles are spent zeroizing uninitialized memory. + /// \details Generally speaking, any operation which changes the size of the SecBlock + /// results in the mark being reset to ELEMS_MAX. In particular, if Assign(), + /// New(), Grow(), CleanNew(), CleanGrow() are called, then the count is reset to + /// ELEMS_MAX. The list is not exhaustive. + /// \since Crypto++ 6.0 + /// \sa Issue 346/CVE-2016-9939 + void SetMark(size_t count) {m_mark = count;} + + /// \brief Assign contents from another SecBlock + /// \param t the other SecBlock + /// \return reference to this SecBlock + /// \details Internally, operator=() calls Assign(). + /// \details If the memory block is reduced in size, then the reclaimed + /// memory is set to 0. If an assignment occurs, then Assign() resets + /// the element count after the previous block is zeroized. + /// \since Crypto++ 2.0 + SecBlock& operator=(const SecBlock &t) + { + // Assign guards for self-assignment + Assign(t); + return *this; + } + + /// \brief Append contents from another SecBlock + /// \param t the other SecBlock + /// \return reference to this SecBlock + /// \details Internally, operator+=() calls Append(). + /// \since Crypto++ 2.0 + SecBlock& operator+=(const SecBlock &t) + { + // Append guards for overflow + Append(t); + return *this; + } + + /// \brief Construct a SecBlock from this and another SecBlock + /// \param t the other SecBlock + /// \return a newly constructed SecBlock that is a concatenation of this + /// and t. + /// \details Internally, a new SecBlock is created from this and a + /// concatenation of t. + /// \since Crypto++ 2.0 + SecBlock operator+(const SecBlock &t) + { + CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size)); + CRYPTOPP_ASSERT((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_size)); + if(!t.m_size) return SecBlock(*this); + + SecBlock result(m_size+t.m_size); + if (m_size) + memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T)); + if (result.m_ptr && t.m_ptr) // GCC analyzer warning + memcpy_s(result.m_ptr+m_size, (result.m_size-m_size)*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); + return result; + } + + /// \brief Bitwise compare two SecBlocks + /// \param t the other SecBlock + /// \return true if the size and bits are equal, false otherwise + /// \details Uses a constant time compare if the arrays are equal size. + /// The constant time compare is VerifyBufsEqual() found in + /// misc.h. + /// \sa operator!=() + /// \since Crypto++ 2.0 + bool operator==(const SecBlock &t) const + { + return m_size == t.m_size && VerifyBufsEqual( + reinterpret_cast(m_ptr), + reinterpret_cast(t.m_ptr), m_size*sizeof(T)); + } + + /// \brief Bitwise compare two SecBlocks + /// \param t the other SecBlock + /// \return true if the size and bits are equal, false otherwise + /// \details Uses a constant time compare if the arrays are equal size. + /// The constant time compare is VerifyBufsEqual() found in + /// misc.h. + /// \details Internally, operator!=() returns the inverse of operator==(). + /// \sa operator==() + /// \since Crypto++ 2.0 + bool operator!=(const SecBlock &t) const + { + return !operator==(t); + } + + /// \brief Change size without preserving contents + /// \param newSize the new size of the memory block + /// \details Old content is not preserved. If the memory block is + /// reduced in size, then the reclaimed content is set to 0. If the + /// memory block grows in size, then the new memory is initialized + /// to 0. New() resets the element count after the previous block + /// is zeroized. + /// \details Internally, this SecBlock calls reallocate(). + /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize() + /// \since Crypto++ 2.0 + void New(size_type newSize) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false); + m_size = newSize; + m_mark = ELEMS_MAX; + } + + /// \brief Change size without preserving contents + /// \param newSize the new size of the memory block + /// \details Old content is not preserved. If the memory block is + /// reduced in size, then the reclaimed content is set to 0. If the + /// memory block grows in size, then the new memory is initialized + /// to 0. CleanNew() resets the element count after the previous + /// block is zeroized. + /// \details Internally, this SecBlock calls New(). + /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize() + /// \since Crypto++ 2.0 + void CleanNew(size_type newSize) + { + New(newSize); + if (m_ptr) {memset_z(m_ptr, 0, m_size*sizeof(T));} + m_mark = ELEMS_MAX; + } + + /// \brief Change size and preserve contents + /// \param newSize the new size of the memory block + /// \details Old content is preserved. New content is not initialized. + /// \details Internally, this SecBlock calls reallocate() when size must + /// increase. If the size does not increase, then CleanGrow() does not + /// take action. If the size must change, then use resize(). CleanGrow() + /// resets the element count after the previous block is zeroized. + /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize() + /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize() + /// \since Crypto++ 2.0 + void Grow(size_type newSize) + { + if (newSize > m_size) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); + m_size = newSize; + } + m_mark = ELEMS_MAX; + } + + /// \brief Change size and preserve contents + /// \param newSize the new size of the memory block + /// \details Old content is preserved. New content is initialized to 0. + /// \details Internally, this SecBlock calls reallocate() when size must + /// increase. If the size does not increase, then CleanGrow() does not + /// take action. If the size must change, then use resize(). CleanGrow() + /// resets the element count after the previous block is zeroized. + /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize() + /// \since Crypto++ 2.0 + void CleanGrow(size_type newSize) + { + if (newSize > m_size) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); + memset_z(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T)); + m_size = newSize; + } + m_mark = ELEMS_MAX; + } + + /// \brief Change size and preserve contents + /// \param newSize the new size of the memory block + /// \details Old content is preserved. If the memory block grows in size, then + /// new memory is not initialized. resize() resets the element count after + /// the previous block is zeroized. + /// \details Internally, this SecBlock calls reallocate(). + /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize() + /// \since Crypto++ 2.0 + void resize(size_type newSize) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); + m_size = newSize; + m_mark = ELEMS_MAX; + } + + /// \brief Swap contents with another SecBlock + /// \param b the other SecBlock + /// \details Internally, std::swap() is called on m_alloc, m_size and m_ptr. + /// \since Crypto++ 2.0 + void swap(SecBlock &b) + { + // Swap must occur on the allocator in case its FixedSize that spilled into the heap. + std::swap(m_alloc, b.m_alloc); + std::swap(m_mark, b.m_mark); + std::swap(m_size, b.m_size); + std::swap(m_ptr, b.m_ptr); + } + +protected: + A m_alloc; + size_type m_mark, m_size; + T *m_ptr; +}; + +#ifdef CRYPTOPP_DOXYGEN_PROCESSING +/// \brief \ref SecBlock "SecBlock" typedef. +class SecByteBlock : public SecBlock {}; +/// \brief \ref SecBlock "SecBlock" typedef. +class SecWordBlock : public SecBlock {}; +/// \brief SecBlock using \ref AllocatorWithCleanup "AllocatorWithCleanup" typedef +class AlignedSecByteBlock : public SecBlock > {}; +#else +typedef SecBlock SecByteBlock; +typedef SecBlock SecWordBlock; +typedef SecBlock > AlignedSecByteBlock; +#endif + +// No need for move semantics on derived class *if* the class does not add any +// data members; see http://stackoverflow.com/q/31755703, and Rule of {0|3|5}. + +/// \brief Fixed size stack-based SecBlock +/// \tparam T class or type +/// \tparam S fixed-size of the stack-based memory block, in elements +/// \tparam A AllocatorBase derived class for allocation and cleanup +template > +class FixedSizeSecBlock : public SecBlock +{ +public: + /// \brief Construct a FixedSizeSecBlock + explicit FixedSizeSecBlock() : SecBlock(S) {} +}; + +/// \brief Fixed size stack-based SecBlock with 16-byte alignment +/// \tparam T class or type +/// \tparam S fixed-size of the stack-based memory block, in elements +/// \tparam T_Align16 boolean that determines whether allocations should be +/// aligned on a 16-byte boundary +template +class FixedSizeAlignedSecBlock : public FixedSizeSecBlock, T_Align16> > +{ +}; + +/// \brief Stack-based SecBlock that grows into the heap +/// \tparam T class or type +/// \tparam S fixed-size of the stack-based memory block, in elements +/// \tparam A AllocatorBase derived class for allocation and cleanup +template > > +class SecBlockWithHint : public SecBlock +{ +public: + /// construct a SecBlockWithHint with a count of elements + explicit SecBlockWithHint(size_t size) : SecBlock(size) {} +}; + +template +inline bool operator==(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (true);} +template +inline bool operator!=(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (false);} + +NAMESPACE_END + +NAMESPACE_BEGIN(std) + +/// \brief Swap two SecBlocks +/// \tparam T class or type +/// \tparam A AllocatorBase derived class for allocation and cleanup +/// \param a the first SecBlock +/// \param b the second SecBlock +template +inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &b) +{ + a.swap(b); +} + +#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)) +// working for STLport 5.1.3 and MSVC 6 SP5 +template +inline CryptoPP::AllocatorWithCleanup<_Tp2>& +__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*) +{ + return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a); +} +#endif + +NAMESPACE_END + +#if defined(CRYPTOPP_MSC_VERSION) +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/secblockfwd.h b/third_party/cryptoppwin/include/cryptopp/secblockfwd.h new file mode 100644 index 00000000..2d68c41e --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/secblockfwd.h @@ -0,0 +1,29 @@ +// secblockfwd.h - written and placed in the public domain by Jeffrey Walton + +/// \file secblockfwd.h +/// \brief Forward declarations for SecBlock +/// \details secblock.h and misc.h have a circular dependency. secblockfwd.h +/// allows the library to sidestep the circular dependency, and reference +/// SecBlock classes without the full implementation. +/// \since Crypto++ 8.3 + +#ifndef CRYPTOPP_SECBLOCKFWD_H +#define CRYPTOPP_SECBLOCKFWD_H + +#include "config.h" + +NAMESPACE_BEGIN(CryptoPP) + +template +class SecBlock; + +template +class AllocatorWithCleanup; + +typedef SecBlock > SecByteBlock; +typedef SecBlock > SecWordBlock; +typedef SecBlock > AlignedSecByteBlock; + +NAMESPACE_END + +#endif // CRYPTOPP_SECBLOCKFWD_H diff --git a/third_party/cryptoppwin/include/cryptopp/seckey.h b/third_party/cryptoppwin/include/cryptopp/seckey.h new file mode 100644 index 00000000..2fc6bedc --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/seckey.h @@ -0,0 +1,444 @@ +// seckey.h - originally written and placed in the public domain by Wei Dai + +/// \file seckey.h +/// \brief Classes and functions for implementing secret key algorithms. + +#ifndef CRYPTOPP_SECKEY_H +#define CRYPTOPP_SECKEY_H + +#include "config.h" +#include "cryptlib.h" +#include "misc.h" +#include "simple.h" +#include "stdcpp.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4189 4296) +#endif + +// Issue 340 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Inverts the cipher's direction +/// \param dir the cipher's direction +/// \return DECRYPTION if \ref CipherDir "dir" is ENCRYPTION, DECRYPTION otherwise +inline CipherDir ReverseCipherDir(CipherDir dir) +{ + return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION; +} + +/// \brief Inherited by algorithms with fixed block size +/// \tparam N the blocksize of the algorithm +template +class FixedBlockSize +{ +public: + /// \brief The block size of the algorithm provided as a constant. + CRYPTOPP_CONSTANT(BLOCKSIZE = N); +}; + +// ************** rounds *************** + +/// \brief Inherited by algorithms with fixed number of rounds +/// \tparam R the number of rounds used by the algorithm +template +class FixedRounds +{ +public: + /// \brief The number of rounds for the algorithm provided as a constant. + CRYPTOPP_CONSTANT(ROUNDS = R); +}; + +/// \brief Inherited by algorithms with variable number of rounds +/// \tparam D Default number of rounds +/// \tparam N Minimum number of rounds +/// \tparam M Maximum number of rounds +template // use INT_MAX here because enums are treated as signed ints +class VariableRounds +{ +public: + /// \brief The default number of rounds for the algorithm provided as a constant. + CRYPTOPP_CONSTANT(DEFAULT_ROUNDS = D); + /// \brief The minimum number of rounds for the algorithm provided as a constant. + CRYPTOPP_CONSTANT(MIN_ROUNDS = N); + /// \brief The maximum number of rounds for the algorithm provided as a constant. + CRYPTOPP_CONSTANT(MAX_ROUNDS = M); + /// \brief The default number of rounds for the algorithm based on key length + /// provided by a static function. + /// \param keylength the size of the key, in bytes + /// \details keylength is unused in the default implementation. + CRYPTOPP_STATIC_CONSTEXPR unsigned int StaticGetDefaultRounds(size_t keylength) + { + return CRYPTOPP_UNUSED(keylength), static_cast(DEFAULT_ROUNDS); + } + +protected: + /// \brief Validates the number of rounds for an algorithm. + /// \param rounds the candidate number of rounds + /// \param alg an Algorithm object used if the number of rounds are invalid + /// \throw InvalidRounds if the number of rounds are invalid + /// \details ThrowIfInvalidRounds() validates the number of rounds and throws if invalid. + inline void ThrowIfInvalidRounds(int rounds, const Algorithm *alg) + { + if (M == INT_MAX) // Coverity and result_independent_of_operands + { + if (rounds < MIN_ROUNDS) + throw InvalidRounds(alg ? alg->AlgorithmName() : std::string("VariableRounds"), rounds); + } + else + { + if (rounds < MIN_ROUNDS || rounds > MAX_ROUNDS) + throw InvalidRounds(alg ? alg->AlgorithmName() : std::string("VariableRounds"), rounds); + } + } + + /// \brief Validates the number of rounds for an algorithm + /// \param param the candidate number of rounds + /// \param alg an Algorithm object used if the number of rounds are invalid + /// \return the number of rounds for the algorithm + /// \throw InvalidRounds if the number of rounds are invalid + /// \details GetRoundsAndThrowIfInvalid() validates the number of rounds and throws if invalid. + inline unsigned int GetRoundsAndThrowIfInvalid(const NameValuePairs ¶m, const Algorithm *alg) + { + int rounds = param.GetIntValueWithDefault("Rounds", DEFAULT_ROUNDS); + ThrowIfInvalidRounds(rounds, alg); + return static_cast(rounds); + } +}; + +// ************** key length *************** + +/// \brief Inherited by keyed algorithms with fixed key length +/// \tparam N Default key length, in bytes +/// \tparam IV_REQ the \ref SimpleKeyingInterface::IV_Requirement "IV requirements" +/// \tparam IV_L default IV length, in bytes +/// \sa SimpleKeyingInterface +template +class FixedKeyLength +{ +public: + /// \brief The default key length used by the algorithm provided as a constant + /// \details KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(KEYLENGTH=N); + /// \brief The minimum key length used by the algorithm provided as a constant + /// \details MIN_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N); + /// \brief The maximum key length used by the algorithm provided as a constant + /// \details MAX_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(MAX_KEYLENGTH=N); + /// \brief The default key length used by the algorithm provided as a constant + /// \details DEFAULT_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=N); + /// \brief The default IV requirements for the algorithm provided as a constant + /// \details The default value is NOT_RESYNCHRONIZABLE. See IV_Requirement + /// in cryptlib.h for allowed values. + CRYPTOPP_CONSTANT(IV_REQUIREMENT = IV_REQ); + /// \brief The default IV length used by the algorithm provided as a constant + /// \details IV_LENGTH is provided in bytes, not bits. The default implementation uses 0. + CRYPTOPP_CONSTANT(IV_LENGTH = IV_L); + /// \brief The default key length for the algorithm provided by a static function. + /// \param keylength the size of the key, in bytes + /// \details The default implementation returns KEYLENGTH. keylength is unused + /// in the default implementation. + CRYPTOPP_STATIC_CONSTEXPR size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength) + { + return CRYPTOPP_UNUSED(keylength), static_cast(KEYLENGTH); + } +}; + +/// \brief Inherited by keyed algorithms with variable key length +/// \tparam D Default key length, in bytes +/// \tparam N Minimum key length, in bytes +/// \tparam M Maximum key length, in bytes +/// \tparam Q Default key length multiple, in bytes. The default multiple is 1. +/// \tparam IV_REQ the \ref SimpleKeyingInterface::IV_Requirement "IV requirements" +/// \tparam IV_L default IV length, in bytes. The default length is 0. +/// \sa SimpleKeyingInterface +template +class VariableKeyLength +{ + // Make these private to avoid Doxygen documenting them in all derived classes + CRYPTOPP_COMPILE_ASSERT(Q > 0); + CRYPTOPP_COMPILE_ASSERT(N % Q == 0); + CRYPTOPP_COMPILE_ASSERT(M % Q == 0); + CRYPTOPP_COMPILE_ASSERT(N < M); + CRYPTOPP_COMPILE_ASSERT(D >= N); + CRYPTOPP_COMPILE_ASSERT(M >= D); + +public: + /// \brief The minimum key length used by the algorithm provided as a constant + /// \details MIN_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N); + /// \brief The maximum key length used by the algorithm provided as a constant + /// \details MAX_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(MAX_KEYLENGTH=M); + /// \brief The default key length used by the algorithm provided as a constant + /// \details DEFAULT_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=D); + /// \brief The key length multiple used by the algorithm provided as a constant + /// \details MAX_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(KEYLENGTH_MULTIPLE=Q); + /// \brief The default IV requirements for the algorithm provided as a constant + /// \details The default value is NOT_RESYNCHRONIZABLE. See IV_Requirement + /// in cryptlib.h for allowed values. + CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ); + /// \brief The default initialization vector length for the algorithm provided as a constant + /// \details IV_LENGTH is provided in bytes, not bits. The default implementation uses 0. + CRYPTOPP_CONSTANT(IV_LENGTH=IV_L); + /// \brief Provides a valid key length for the algorithm provided by a static function. + /// \param keylength the size of the key, in bytes + /// \details 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 keylength is a multiple of KEYLENGTH_MULTIPLE, + /// then keylength is returned. Otherwise, the function returns keylength rounded + /// \a down to the next smaller multiple of KEYLENGTH_MULTIPLE. + /// \details keylength is provided in bytes, not bits. + CRYPTOPP_STATIC_CONSTEXPR size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength) + { + return (keylength <= N) ? N : + (keylength >= M) ? M : + (keylength+Q-1) - (keylength+Q-1)%Q; + } +}; + +/// \brief Provides key lengths based on another class's key length +/// \tparam T another FixedKeyLength or VariableKeyLength class +/// \tparam IV_REQ the \ref SimpleKeyingInterface::IV_Requirement "IV requirements" +/// \tparam IV_L default IV length, in bytes +/// \sa SimpleKeyingInterface +template +class SameKeyLengthAs +{ +public: + /// \brief The minimum key length used by the algorithm provided as a constant + /// \details MIN_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(MIN_KEYLENGTH=T::MIN_KEYLENGTH); + /// \brief The maximum key length used by the algorithm provided as a constant + /// \details MIN_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(MAX_KEYLENGTH=T::MAX_KEYLENGTH); + /// \brief The default key length used by the algorithm provided as a constant + /// \details MIN_KEYLENGTH is provided in bytes, not bits + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH); + /// \brief The default IV requirements for the algorithm provided as a constant + /// \details The default value is NOT_RESYNCHRONIZABLE. See IV_Requirement + /// in cryptlib.h for allowed values. + CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ); + /// \brief The default initialization vector length for the algorithm provided as a constant + /// \details IV_LENGTH is provided in bytes, not bits. The default implementation uses 0. + CRYPTOPP_CONSTANT(IV_LENGTH=IV_L); + /// \brief Provides a valid key length for the algorithm provided by a static function. + /// \param keylength the size of the key, in bytes + /// \details 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 keylength is a multiple of KEYLENGTH_MULTIPLE, + /// then keylength is returned. Otherwise, the function returns keylength rounded + /// \a down to the next smaller multiple of KEYLENGTH_MULTIPLE. + /// \details keylength is provided in bytes, not bits. + CRYPTOPP_STATIC_CONSTEXPR size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength) + {return T::StaticGetValidKeyLength(keylength);} +}; + +// ************** implementation helper for SimpleKeyingInterface *************** + +/// \brief Provides a base implementation of SimpleKeyingInterface +/// \tparam BASE a SimpleKeyingInterface derived class +/// \tparam INFO a SimpleKeyingInterface derived class +/// \details SimpleKeyingInterfaceImpl() provides a default implementation for ciphers providing a keying interface. +/// Functions are virtual and not eligible for C++11 constexpr-ness. +/// \sa Algorithm(), SimpleKeyingInterface() +template +class CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : public BASE +{ +public: + /// \brief The minimum key length used by the algorithm + /// \return minimum key length used by the algorithm, in bytes + size_t MinKeyLength() const + {return INFO::MIN_KEYLENGTH;} + + /// \brief The maximum key length used by the algorithm + /// \return maximum key length used by the algorithm, in bytes + size_t MaxKeyLength() const + {return static_cast(INFO::MAX_KEYLENGTH);} + + /// \brief The default key length used by the algorithm + /// \return default key length used by the algorithm, in bytes + size_t DefaultKeyLength() const + {return INFO::DEFAULT_KEYLENGTH;} + + /// \brief Provides 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 INFO::StaticGetValidKeyLength(keylength);} + + /// \brief The default IV requirements for the algorithm + /// \details The default value is NOT_RESYNCHRONIZABLE. See IV_Requirement + /// in cryptlib.h for allowed values. + SimpleKeyingInterface::IV_Requirement IVRequirement() const + {return static_cast(INFO::IV_REQUIREMENT);} + + /// \brief The initialization vector length for the algorithm + /// \details IVSize is provided in bytes, not bits. The default implementation uses + /// IV_LENGTH, which is 0. + unsigned int IVSize() const + {return INFO::IV_LENGTH;} +}; + +/// \brief Provides a base implementation of Algorithm and SimpleKeyingInterface for block ciphers +/// \tparam INFO a SimpleKeyingInterface derived class +/// \tparam BASE a SimpleKeyingInterface derived class +/// \details BlockCipherImpl() provides a default implementation for block ciphers using AlgorithmImpl() +/// and SimpleKeyingInterfaceImpl(). Functions are virtual and not eligible for C++11 constexpr-ness. +/// \sa Algorithm(), SimpleKeyingInterface(), AlgorithmImpl(), SimpleKeyingInterfaceImpl() +template +class CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl > > +{ +public: + /// Provides the block size of the algorithm + /// \return the block size of the algorithm, in bytes + unsigned int BlockSize() const {return this->BLOCKSIZE;} +}; + +/// \brief Provides class member functions to key a block cipher +/// \tparam DIR a CipherDir +/// \tparam BASE a BlockCipherImpl derived class +template +class BlockCipherFinal : public ClonableImpl, BASE> +{ +public: + /// \brief Construct a default BlockCipherFinal + /// \details The cipher is not keyed. + BlockCipherFinal() {} + + /// \brief Construct a BlockCipherFinal + /// \param key a byte array used to key the cipher + /// \details key must be at least DEFAULT_KEYLENGTH in length. Internally, the function calls + /// SimpleKeyingInterface::SetKey. + BlockCipherFinal(const byte *key) + {this->SetKey(key, this->DEFAULT_KEYLENGTH);} + + /// \brief Construct a BlockCipherFinal + /// \param key a byte array used to key the cipher + /// \param length the length of the byte array + /// \details key must be at least DEFAULT_KEYLENGTH in length. Internally, the function calls + /// SimpleKeyingInterface::SetKey. + BlockCipherFinal(const byte *key, size_t length) + {this->SetKey(key, length);} + + /// \brief Construct a BlockCipherFinal + /// \param key a byte array used to key the cipher + /// \param length the length of the byte array + /// \param rounds the number of rounds + /// \details key must be at least DEFAULT_KEYLENGTH in length. Internally, the function calls + /// SimpleKeyingInterface::SetKeyWithRounds. + BlockCipherFinal(const byte *key, size_t length, unsigned int rounds) + {this->SetKeyWithRounds(key, length, rounds);} + + /// \brief Provides the direction of the cipher + /// \return true if DIR is ENCRYPTION, false otherwise + /// \sa GetCipherDirection(), IsPermutation() + bool IsForwardTransformation() const {return DIR == ENCRYPTION;} +}; + +/// \brief Provides a base implementation of Algorithm and SimpleKeyingInterface for message authentication codes +/// \tparam INFO a SimpleKeyingInterface derived class +/// \tparam BASE a SimpleKeyingInterface derived class +/// \details MessageAuthenticationCodeImpl() provides a default implementation for message authentication codes +/// using AlgorithmImpl() and SimpleKeyingInterfaceImpl(). Functions are virtual and not subject to C++11 +/// constexpr. +/// \sa Algorithm(), SimpleKeyingInterface(), AlgorithmImpl(), SimpleKeyingInterfaceImpl() +template +class MessageAuthenticationCodeImpl : public AlgorithmImpl, INFO> +{ +}; + +/// \brief Provides class member functions to key a message authentication code +/// \tparam BASE a BlockCipherImpl derived class +/// \details A default implementation for MessageAuthenticationCode +template +class MessageAuthenticationCodeFinal : public ClonableImpl, MessageAuthenticationCodeImpl > +{ +public: + /// \brief Construct a default MessageAuthenticationCodeFinal + /// \details The message authentication code is not keyed. + MessageAuthenticationCodeFinal() {} + /// \brief Construct a BlockCipherFinal + /// \param key a byte array used to key the algorithm + /// \details key must be at least DEFAULT_KEYLENGTH in length. Internally, the function calls + /// SimpleKeyingInterface::SetKey. + MessageAuthenticationCodeFinal(const byte *key) + {this->SetKey(key, this->DEFAULT_KEYLENGTH);} + /// \brief Construct a BlockCipherFinal + /// \param key a byte array used to key the algorithm + /// \param length the length of the byte array + /// \details key must be at least DEFAULT_KEYLENGTH in length. Internally, the function calls + /// SimpleKeyingInterface::SetKey. + MessageAuthenticationCodeFinal(const byte *key, size_t length) + {this->SetKey(key, length);} +}; + +// ************** documentation *************** + +/// \brief Provides Encryption and Decryption typedefs used by derived classes to +/// implement a block cipher +/// \details These objects usually should not be used directly. See CipherModeDocumentation +/// instead. Each class derived from this one defines two types, Encryption and Decryption, +/// both of which implement the BlockCipher interface. +struct BlockCipherDocumentation +{ + /// implements the BlockCipher interface + typedef BlockCipher Encryption; + /// implements the BlockCipher interface + typedef BlockCipher Decryption; +}; + +/// \brief Provides Encryption and Decryption typedefs used by derived classes to +/// implement a symmetric cipher +/// \details Each class derived from this one defines two types, Encryption and Decryption, +/// both of which implement the SymmetricCipher interface. Two types of classes derive +/// from this class: stream ciphers and block cipher modes. Stream ciphers can be used +/// alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation +/// for more for information about using cipher modes and block ciphers. +struct SymmetricCipherDocumentation +{ + /// implements the SymmetricCipher interface + typedef SymmetricCipher Encryption; + /// implements the SymmetricCipher interface + typedef SymmetricCipher Decryption; +}; + +/// \brief Provides Encryption and Decryption typedefs used by derived classes to +/// implement an authenticated encryption cipher +/// \details Each class derived from this one defines two types, Encryption and Decryption, +/// both of which implement the AuthenticatedSymmetricCipher interface. +struct AuthenticatedSymmetricCipherDocumentation +{ + /// implements the AuthenticatedSymmetricCipher interface + typedef AuthenticatedSymmetricCipher Encryption; + /// implements the AuthenticatedSymmetricCipher interface + typedef AuthenticatedSymmetricCipher Decryption; +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +// Issue 340 +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/seed.h b/third_party/cryptoppwin/include/cryptopp/seed.h new file mode 100644 index 00000000..63ee028b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/seed.h @@ -0,0 +1,44 @@ +// seed.h - originally written and placed in the public domain by Wei Dai + +/// \file seed.h +/// \brief Classes for the SEED block cipher +/// \since Crypto++ 5.6.0 + +#ifndef CRYPTOPP_SEED_H +#define CRYPTOPP_SEED_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SEED block cipher information +/// \since Crypto++ 5.6.0 +struct SEED_Info : public FixedBlockSize<16>, public FixedKeyLength<16>, public FixedRounds<16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SEED";} +}; + +/// \brief SEED block cipher +/// \sa SEED +/// \since Crypto++ 5.6.0 +class SEED : public SEED_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + FixedSizeSecBlock m_k; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/serpent.h b/third_party/cryptoppwin/include/cryptopp/serpent.h new file mode 100644 index 00000000..3fa3379a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/serpent.h @@ -0,0 +1,72 @@ +// serpent.h - originally written and placed in the public domain by Wei Dai + +/// \file serpent.h +/// \brief Classes for the Serpent block cipher +/// \sa A +/// Candidate Block Cipher for the Advanced Encryption Standard + +#ifndef CRYPTOPP_SERPENT_H +#define CRYPTOPP_SERPENT_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Serpent block cipher information +/// \since Crypto++ 3.1 +struct Serpent_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8>, public FixedRounds<32> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Serpent";} +}; + +/// \brief Serpent block cipher +/// \sa Serpent on the +/// Crypto++ wiki, A +/// Candidate Block Cipher for the Advanced Encryption Standard +/// \since Crypto++ 3.1 +class Serpent : public Serpent_Info, public BlockCipherDocumentation +{ + /// \brief Serpen block cipher base implementation + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 3.1 + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock m_key; + }; + + /// \brief Serpent encryption transformation + /// \details Enc provides the encryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 3.1 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief Serpent decryption transformation + /// \details Dec provides the decryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 3.1 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Serpent::Encryption SerpentEncryption; +typedef Serpent::Decryption SerpentDecryption; + +NAMESPACE_END + +#endif // CRYPTOPP_SERPENT_H diff --git a/third_party/cryptoppwin/include/cryptopp/serpentp.h b/third_party/cryptoppwin/include/cryptopp/serpentp.h new file mode 100644 index 00000000..124b08c5 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/serpentp.h @@ -0,0 +1,439 @@ +// private header for Serpent and Sosemanuk + +#ifndef CRYPTOPP_SERPENTP_H +#define CRYPTOPP_SERPENTP_H + +NAMESPACE_BEGIN(CryptoPP) + +// linear transformation +#define LT(i,a,b,c,d,e) {\ + a = rotlConstant<13>(a); \ + c = rotlConstant<3>(c); \ + d = rotlConstant<7>(d ^ c ^ (a << 3)); \ + b = rotlConstant<1>(b ^ a ^ c); \ + a = rotlConstant<5>(a ^ b ^ d); \ + c = rotlConstant<22>(c ^ d ^ (b << 7));} + +// inverse linear transformation +#define ILT(i,a,b,c,d,e) {\ + c = rotrConstant<22>(c); \ + a = rotrConstant<5>(a); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + b = rotrConstant<1>(b); \ + d = rotrConstant<7>(d) ^ c ^ (a << 3); \ + b ^= a ^ c; \ + c = rotrConstant<3>(c); \ + a = rotrConstant<13>(a);} + +// order of output from S-box functions +#define beforeS0(f) f(0,a,b,c,d,e) +#define afterS0(f) f(1,b,e,c,a,d) +#define afterS1(f) f(2,c,b,a,e,d) +#define afterS2(f) f(3,a,e,b,d,c) +#define afterS3(f) f(4,e,b,d,c,a) +#define afterS4(f) f(5,b,a,e,c,d) +#define afterS5(f) f(6,a,c,b,e,d) +#define afterS6(f) f(7,a,c,d,b,e) +#define afterS7(f) f(8,d,e,b,a,c) + +// order of output from inverse S-box functions +#define beforeI7(f) f(8,a,b,c,d,e) +#define afterI7(f) f(7,d,a,b,e,c) +#define afterI6(f) f(6,a,b,c,e,d) +#define afterI5(f) f(5,b,d,e,c,a) +#define afterI4(f) f(4,b,c,e,a,d) +#define afterI3(f) f(3,a,b,e,c,d) +#define afterI2(f) f(2,b,d,e,c,a) +#define afterI1(f) f(1,a,b,c,e,d) +#define afterI0(f) f(0,a,d,b,e,c) + +// The instruction sequences for the S-box functions +// come from Dag Arne Osvik's paper "Speeding up Serpent". + +#define S0(i, r0, r1, r2, r3, r4) \ + { \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r4 ^= r2; \ + r1 ^= r0; \ + r0 |= r3; \ + r0 ^= r4; \ + r4 ^= r3; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 ^= r4; \ + r4 = ~r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r1 ^= r4; \ + r3 |= r0; \ + r1 ^= r3; \ + r4 ^= r3; \ + } + +#define I0(i, r0, r1, r2, r3, r4) \ + { \ + r2 = ~r2; \ + r4 = r1; \ + r1 |= r0; \ + r4 = ~r4; \ + r1 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 &= r3; \ + r4 ^= r0; \ + r0 |= r1; \ + r0 ^= r2; \ + r3 ^= r4; \ + r2 ^= r1; \ + r3 ^= r0; \ + r3 ^= r1; \ + r2 &= r3; \ + r4 ^= r2; \ + } + +#define S1(i, r0, r1, r2, r3, r4) \ + { \ + r0 = ~r0; \ + r2 = ~r2; \ + r4 = r0; \ + r0 &= r1; \ + r2 ^= r0; \ + r0 |= r3; \ + r3 ^= r2; \ + r1 ^= r0; \ + r0 ^= r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r2 |= r0; \ + r2 &= r4; \ + r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r2; \ + r0 ^= r4; \ + } + +#define I1(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r1; \ + r1 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r3 ^= r0; \ + r0 |= r1; \ + r2 ^= r3; \ + r0 ^= r4; \ + r0 |= r2; \ + r1 ^= r3; \ + r0 ^= r1; \ + r1 |= r3; \ + r1 ^= r0; \ + r4 = ~r4; \ + r4 ^= r1; \ + r1 |= r0; \ + r1 ^= r0; \ + r1 |= r4; \ + r3 ^= r1; \ + } + +#define S2(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r0; \ + r0 &= r2; \ + r0 ^= r3; \ + r2 ^= r1; \ + r2 ^= r0; \ + r3 |= r4; \ + r3 ^= r1; \ + r4 ^= r2; \ + r1 = r3; \ + r3 |= r4; \ + r3 ^= r0; \ + r0 &= r1; \ + r4 ^= r0; \ + r1 ^= r3; \ + r1 ^= r4; \ + r4 = ~r4; \ + } + +#define I2(i, r0, r1, r2, r3, r4) \ + { \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r3; \ + r3 &= r2; \ + r3 ^= r1; \ + r1 |= r2; \ + r1 ^= r4; \ + r4 &= r3; \ + r2 ^= r3; \ + r4 &= r0; \ + r4 ^= r2; \ + r2 &= r1; \ + r2 |= r0; \ + r3 = ~r3; \ + r2 ^= r3; \ + r0 ^= r3; \ + r0 &= r1; \ + r3 ^= r4; \ + r3 ^= r0; \ + } + +#define S3(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r0; \ + r0 |= r3; \ + r3 ^= r1; \ + r1 &= r4; \ + r4 ^= r2; \ + r2 ^= r3; \ + r3 &= r0; \ + r4 |= r1; \ + r3 ^= r4; \ + r0 ^= r1; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r2; \ + r1 |= r0; \ + r1 ^= r2; \ + r0 ^= r3; \ + r2 = r1; \ + r1 |= r3; \ + r1 ^= r0; \ + } + +#define I3(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r4; \ + r4 ^= r3; \ + r3 |= r1; \ + r3 ^= r2; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 |= r3; \ + r0 ^= r1; \ + r4 ^= r2; \ + r2 &= r3; \ + r1 |= r3; \ + r1 ^= r2; \ + r4 ^= r0; \ + r2 ^= r4; \ + } + +#define S4(i, r0, r1, r2, r3, r4) \ + { \ + r1 ^= r3; \ + r3 = ~r3; \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r1 ^= r2; \ + r4 ^= r3; \ + r0 ^= r4; \ + r2 &= r4; \ + r2 ^= r0; \ + r0 &= r1; \ + r3 ^= r0; \ + r4 |= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r2 &= r3; \ + r0 = ~r0; \ + r4 ^= r2; \ + } + +#define I4(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 &= r3; \ + r2 ^= r1; \ + r1 |= r3; \ + r1 &= r0; \ + r4 ^= r2; \ + r4 ^= r1; \ + r1 &= r2; \ + r0 = ~r0; \ + r3 ^= r4; \ + r1 ^= r3; \ + r3 &= r0; \ + r3 ^= r2; \ + r0 ^= r1; \ + r2 &= r0; \ + r3 ^= r0; \ + r2 ^= r4; \ + r2 |= r3; \ + r3 ^= r0; \ + r2 ^= r1; \ + } + +#define S5(i, r0, r1, r2, r3, r4) \ + { \ + r0 ^= r1; \ + r1 ^= r3; \ + r3 = ~r3; \ + r4 = r1; \ + r1 &= r0; \ + r2 ^= r3; \ + r1 ^= r2; \ + r2 |= r4; \ + r4 ^= r3; \ + r3 &= r1; \ + r3 ^= r0; \ + r4 ^= r1; \ + r4 ^= r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r0 ^= r4; \ + r4 |= r3; \ + r2 ^= r4; \ + } + +#define I5(i, r0, r1, r2, r3, r4) \ + { \ + r1 = ~r1; \ + r4 = r3; \ + r2 ^= r1; \ + r3 |= r0; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 ^= r4; \ + r4 |= r0; \ + r4 ^= r1; \ + r1 &= r2; \ + r1 ^= r3; \ + r4 ^= r2; \ + r3 &= r4; \ + r4 ^= r1; \ + r3 ^= r0; \ + r3 ^= r4; \ + r4 = ~r4; \ + } + +#define S6(i, r0, r1, r2, r3, r4) \ + { \ + r2 = ~r2; \ + r4 = r3; \ + r3 &= r0; \ + r0 ^= r4; \ + r3 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r2 ^= r0; \ + r0 |= r1; \ + r2 ^= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r4 ^= r3; \ + r4 ^= r0; \ + r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ + } + +#define I6(i, r0, r1, r2, r3, r4) \ + { \ + r0 ^= r2; \ + r4 = r2; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 = ~r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r4 |= r0; \ + r0 ^= r2; \ + r3 ^= r4; \ + r4 ^= r1; \ + r1 &= r3; \ + r1 ^= r0; \ + r0 ^= r3; \ + r0 |= r2; \ + r3 ^= r1; \ + r4 ^= r0; \ + } + +#define S7(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 &= r1; \ + r2 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r2 ^= r1; \ + r1 ^= r0; \ + r0 |= r4; \ + r0 ^= r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r3 &= r0; \ + r3 ^= r4; \ + r4 ^= r2; \ + r2 &= r0; \ + r4 = ~r4; \ + r2 ^= r4; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r1; \ + } + +#define I7(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r4 |= r3; \ + r3 ^= r1; \ + r1 |= r0; \ + r0 ^= r2; \ + r2 &= r4; \ + r1 ^= r2; \ + r2 ^= r0; \ + r0 |= r2; \ + r3 &= r4; \ + r0 ^= r3; \ + r4 ^= r1; \ + r3 ^= r4; \ + r4 |= r0; \ + r3 ^= r2; \ + r4 ^= r2; \ + } + +// key xor +#define KX(r, a, b, c, d, e) {\ + a ^= k[4 * r + 0]; \ + b ^= k[4 * r + 1]; \ + c ^= k[4 * r + 2]; \ + d ^= k[4 * r + 3];} + +#define LK(r, a, b, c, d, e) {\ + a = k[(8-r)*4 + 0]; \ + b = k[(8-r)*4 + 1]; \ + c = k[(8-r)*4 + 2]; \ + d = k[(8-r)*4 + 3];} + +#define SK(r, a, b, c, d, e) {\ + k[(8-r)*4 + 4] = a; \ + k[(8-r)*4 + 5] = b; \ + k[(8-r)*4 + 6] = c; \ + k[(8-r)*4 + 7] = d;} + +void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen); + +NAMESPACE_END + +#endif // CRYPTOPP_SERPENTP_H diff --git a/third_party/cryptoppwin/include/cryptopp/sha.h b/third_party/cryptoppwin/include/cryptopp/sha.h new file mode 100644 index 00000000..d4a09d7d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sha.h @@ -0,0 +1,210 @@ +// sha.h - originally written and placed in the public domain by Wei Dai + +/// \file sha.h +/// \brief Classes for SHA-1 and SHA-2 family of message digests +/// \since SHA1 since Crypto++ 1.0, SHA2 since Crypto++ 4.0, ARMv8 SHA since +/// Crypto++ 6.0, Intel SHA since Crypto++ 6.0, Power8 SHA since Crypto++ 6.1 + +#ifndef CRYPTOPP_SHA_H +#define CRYPTOPP_SHA_H + +#include "config.h" +#include "iterhash.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_SHA_ASM 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SHA-1 message digest +/// \sa SHA-1 +/// \since SHA1 since Crypto++ 1.0, SHA2 since Crypto++ 4.0, ARMv8 SHA since +/// Crypto++ 6.0, Intel SHA since Crypto++ 6.0 +class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform +{ +public: + /// \brief Initialize state array + /// \param state the state of the hash + /// \details InitState sets a state array to SHA1 initial values + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array must be 16-byte aligned for SSE2. + static void CRYPTOPP_API InitState(HashWordType *state); + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + /// \details Transform operates the hash on data. When the call is invoked + /// digest holds initial state. Upon return digest holds the hash + /// or updated state. + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array and data must be 16-byte aligned for SSE2. + static void CRYPTOPP_API Transform(HashWordType *digest, const HashWordType *data); + /// \brief The algorithm name + /// \return C-style string "SHA-1" + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "SHA-1";} + // Algorithm class + std::string AlgorithmProvider() const; + +protected: + size_t HashMultipleBlocks(const HashWordType *input, size_t length); +}; + +/// \brief SHA-256 message digest +/// \sa SHA-256 +/// \since SHA2 since Crypto++ 4.0, ARMv8 SHA since Crypto++ 6.0, +/// Intel SHA since Crypto++ 6.0, Power8 SHA since Crypto++ 6.1 +class CRYPTOPP_DLL SHA256 : public IteratedHashWithStaticTransform +{ +public: + /// \brief Initialize state array + /// \param state the state of the hash + /// \details InitState sets a state array to SHA256 initial values + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array must be 16-byte aligned for SSE2. + static void CRYPTOPP_API InitState(HashWordType *state); + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + /// \details Transform operates the hash on data. When the call is invoked + /// digest holds initial state. Upon return digest holds the hash + /// or updated state. + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array and data must be 16-byte aligned for SSE2. + static void CRYPTOPP_API Transform(HashWordType *digest, const HashWordType *data); + /// \brief The algorithm name + /// \return C-style string "SHA-256" + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "SHA-256";} + + // Algorithm class + std::string AlgorithmProvider() const; + +protected: + size_t HashMultipleBlocks(const HashWordType *input, size_t length); +}; + +/// \brief SHA-224 message digest +/// \sa SHA-224 +/// \since SHA2 since Crypto++ 4.0, ARMv8 SHA since Crypto++ 6.0, +/// Intel SHA since Crypto++ 6.0, Power8 SHA since Crypto++ 6.1 +class CRYPTOPP_DLL SHA224 : public IteratedHashWithStaticTransform +{ +public: + /// \brief Initialize state array + /// \param state the state of the hash + /// \details InitState sets a state array to SHA224 initial values + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array must be 16-byte aligned for SSE2. + static void CRYPTOPP_API InitState(HashWordType *state); + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + /// \details Transform operates the hash on data. When the call is invoked + /// digest holds initial state. Upon return digest holds the hash + /// or updated state. + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array and data must be 16-byte aligned for SSE2. + static void CRYPTOPP_API Transform(HashWordType *digest, const HashWordType *data) {SHA256::Transform(digest, data);} + /// \brief The algorithm name + /// \return C-style string "SHA-224" + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";} + + // Algorithm class + std::string AlgorithmProvider() const; + +protected: + size_t HashMultipleBlocks(const HashWordType *input, size_t length); +}; + +/// \brief SHA-512 message digest +/// \sa SHA-512 +/// \since SHA2 since Crypto++ 4.0, Power8 SHA since Crypto++ 6.1 +class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform +{ +public: + /// \brief Initialize state array + /// \param state the state of the hash + /// \details InitState sets a state array to SHA512 initial values + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array must be 16-byte aligned for SSE2. + static void CRYPTOPP_API InitState(HashWordType *state); + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + /// \details Transform operates the hash on data. When the call is invoked + /// digest holds initial state. Upon return digest holds the hash + /// or updated state. + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array and data must be 16-byte aligned for SSE2. + static void CRYPTOPP_API Transform(HashWordType *digest, const HashWordType *data); + /// \brief The algorithm name + /// \return C-style string "SHA-512" + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "SHA-512";} + + // Algorithm class + std::string AlgorithmProvider() const; +}; + +/// \brief SHA-384 message digest +/// \sa SHA-384 +/// \since SHA2 since Crypto++ 4.0, Power8 SHA since Crypto++ 6.1 +class CRYPTOPP_DLL SHA384 : public IteratedHashWithStaticTransform +{ +public: + /// \brief Initialize state array + /// \param state the state of the hash + /// \details InitState sets a state array to SHA384 initial values + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array must be 16-byte aligned for SSE2. + static void CRYPTOPP_API InitState(HashWordType *state); + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + /// \details Transform operates the hash on data. When the call is invoked + /// digest holds initial state. Upon return digest holds the hash + /// or updated state. + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState and Transform. External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + /// \note On Intel platforms the state array and data must be 16-byte aligned for SSE2. + static void CRYPTOPP_API Transform(HashWordType *digest, const HashWordType *data) {SHA512::Transform(digest, data);} + /// \brief The algorithm name + /// \return C-style string "SHA-384" + CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";} + + // Algorithm class + std::string AlgorithmProvider() const; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/sha1_armv4.h b/third_party/cryptoppwin/include/cryptopp/sha1_armv4.h new file mode 100644 index 00000000..97f36717 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sha1_armv4.h @@ -0,0 +1,23 @@ +/* Header file for use with Cryptogam's ARMv4 SHA1. */ +/* Also see http://www.openssl.org/~appro/cryptogams/ */ +/* https://wiki.openssl.org/index.php/Cryptogams_SHA. */ + +#ifndef CRYPTOGAMS_SHA1_ARMV4_H +#define CRYPTOGAMS_SHA1_ARMV4_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Crypto++ modified sha1_block_data_order to pass caps as a parameter. */ +/* Also see https://github.com/weidai11/cryptopp/issues/846. */ +void cryptogams_sha1_block_data_order(void *state, const void *data, size_t blocks); + +/* Cryptogams arm caps */ +#define CRYPTOGAMS_ARMV7_NEON (1<<0) + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTOGAMS_SHA1_ARMV4_H */ diff --git a/third_party/cryptoppwin/include/cryptopp/sha256_armv4.h b/third_party/cryptoppwin/include/cryptopp/sha256_armv4.h new file mode 100644 index 00000000..5a4b88e2 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sha256_armv4.h @@ -0,0 +1,23 @@ +/* Header file for use with Cryptogam's ARMv4 SHA1. */ +/* Also see http://www.openssl.org/~appro/cryptogams/ */ +/* https://wiki.openssl.org/index.php/Cryptogams_SHA. */ + +#ifndef CRYPTOGAMS_SHA256_ARMV4_H +#define CRYPTOGAMS_SHA256_ARMV4_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Crypto++ modified cryptogams_sha256_block_data_order to pass caps as a parameter. */ +/* Also see https://github.com/weidai11/cryptopp/issues/846. */ +void cryptogams_sha256_block_data_order(void *state, const void *data, size_t blocks); + +/* Cryptogams arm caps */ +#define CRYPTOGAMS_ARMV7_NEON (1<<0) + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTOGAMS_SHA256_ARMV4_H */ diff --git a/third_party/cryptoppwin/include/cryptopp/sha3.h b/third_party/cryptoppwin/include/cryptopp/sha3.h new file mode 100644 index 00000000..97fce4b6 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sha3.h @@ -0,0 +1,106 @@ +// sha3.h - originally written and placed in the public domain by Wei Dai + +/// \file sha3.h +/// \brief Classes for SHA3 message digests +/// \details The Crypto++ implementation conforms to the FIPS 202 version of SHA3 using F1600 with XOF d=0x06. +/// Previous behavior (XOF d=0x01) is available in Keccak classes. +/// \sa SHA-3, +/// SHA-3 STANDARD (FIPS 202). +/// \since Crypto++ 5.6.2 + +#ifndef CRYPTOPP_SHA3_H +#define CRYPTOPP_SHA3_H + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SHA3 message digest base class +/// \details The Crypto++ implementation conforms to FIPS 202 version of SHA3 using F1600 with XOF d=0x06. +/// Previous behavior (XOF d=0x01) is available in Keccak classes. +/// \details SHA3 is the base class for SHA3_224, SHA3_256, SHA3_384 and SHA3_512. +/// Library users should instantiate a derived class, and only use SHA3 +/// as a base class reference or pointer. +/// \sa Keccak, SHA3_224, SHA3_256, SHA3_384 and SHA3_512. +/// \since Crypto++ 5.6.2 +class SHA3 : public HashTransformation +{ +protected: + /// \brief Construct a SHA3 + /// \param digestSize the digest size, in bytes + /// \details SHA3 is the base class for SHA3_224, SHA3_256, SHA3_384 and SHA3_512. + /// Library users should instantiate a derived class, and only use SHA3 + /// 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.2 + SHA3(unsigned int digestSize) : m_digestSize(digestSize) {Restart();} + +public: + unsigned int DigestSize() const {return m_digestSize;} + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + void Update(const byte *input, size_t length); + void Restart(); + void TruncatedFinal(byte *hash, size_t size); + +protected: + inline unsigned int r() const {return BlockSize();} + + FixedSizeSecBlock m_state; + unsigned int m_digestSize, m_counter; +}; + +/// \brief SHA3 message digest template +/// \tparam T_DigestSize the size of the digest, in bytes +/// \since Crypto++ 5.6.2 +template +class SHA3_Final : public SHA3 +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize); + CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE); + static std::string StaticAlgorithmName() + { return "SHA3-" + IntToString(DIGESTSIZE * 8); } + + /// \brief Construct a SHA3-X message digest + SHA3_Final() : SHA3(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 r. + unsigned int BlockSize() const { return BLOCKSIZE; } + + std::string AlgorithmName() const { return StaticAlgorithmName(); } + +private: +#if !defined(__BORLANDC__) + // ensure there was no underflow in the math + CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); +#endif +}; + +/// \brief SHA3-224 message digest +/// \since Crypto++ 5.6.2 +class SHA3_224 : public SHA3_Final<28> {}; + +/// \brief SHA3-256 message digest +/// \since Crypto++ 5.6.2 +class SHA3_256 : public SHA3_Final<32> {}; + +/// \brief SHA3-384 message digest +/// \since Crypto++ 5.6.2 +class SHA3_384 : public SHA3_Final<48> {}; + +/// \brief SHA3-512 message digest +/// \since Crypto++ 5.6.2 +class SHA3_512 : public SHA3_Final<64> {}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/sha512_armv4.h b/third_party/cryptoppwin/include/cryptopp/sha512_armv4.h new file mode 100644 index 00000000..cead986b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sha512_armv4.h @@ -0,0 +1,23 @@ +/* Header file for use with Cryptogam's ARMv4 SHA512. */ +/* Also see http://www.openssl.org/~appro/cryptogams/ */ +/* https://wiki.openssl.org/index.php/Cryptogams_SHA. */ + +#ifndef CRYPTOGAMS_SHA512_ARMV4_H +#define CRYPTOGAMS_SHA512_ARMV4_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Crypto++ modified cryptogams_sha512_block_data_order to pass caps as a parameter. */ +/* Also see https://github.com/weidai11/cryptopp/issues/846. */ +void cryptogams_sha512_block_data_order(void *state, const void *data, size_t blocks); + +/* Cryptogams arm caps */ +#define CRYPTOGAMS_ARMV7_NEON (1<<0) + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTOGAMS_SHA512_ARMV4_H */ diff --git a/third_party/cryptoppwin/include/cryptopp/shacal2.h b/third_party/cryptoppwin/include/cryptopp/shacal2.h new file mode 100644 index 00000000..9f729582 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/shacal2.h @@ -0,0 +1,66 @@ +// shacal.h - originally written and placed in the public domain by Wei Dai + +/// \file shacal2.h +/// \brief Classes for the SHACAL-2 block cipher +/// \since Crypto++ 5.2, Intel SHA since Crypto++ 6.0 + +#ifndef CRYPTOPP_SHACAL2_H +#define CRYPTOPP_SHACAL2_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SHACAL2 block cipher information +struct SHACAL2_Info : public FixedBlockSize<32>, public VariableKeyLength<16, 16, 64> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SHACAL-2";} +}; + +/// \brief SHACAL2 block cipher +/// \since Crypto++ 5.2, Intel SHA since Crypto++ 6.0 +/// \sa SHACAL-2 +class SHACAL2 : public SHACAL2_Info, public BlockCipherDocumentation +{ + /// \brief SHACAL2 block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + std::string AlgorithmProvider() const; + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeAlignedSecBlock m_key; + + static const word32 K[64]; + }; + + /// \brief SHACAL2 block cipher transformation functions + /// \details Encryption transformation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief SHACAL2 block cipher transformation functions + /// \details Decryption transformation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef SHACAL2::Encryption SHACAL2Encryption; +typedef SHACAL2::Decryption SHACAL2Decryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/shake.h b/third_party/cryptoppwin/include/cryptopp/shake.h new file mode 100644 index 00000000..4d52132d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/shake.h @@ -0,0 +1,161 @@ +// shake.h - written and placed in the public domain by Jeffrey Walton + +/// \file shake.h +/// \brief Classes for SHAKE message digests +/// \details The library provides byte oriented SHAKE128 and SHAKE256 using F1600. +/// FIPS 202 allows nearly unlimited output sizes, but Crypto++ limits the output +/// size to UINT_MAX due underlying data types. +/// \sa Keccak, SHA3, SHAKE128, SHAKE256, +/// FIPS 202, +/// SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions +/// \since Crypto++ 8.1 + +#ifndef CRYPTOPP_SHAKE_H +#define CRYPTOPP_SHAKE_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SHAKE message digest base class +/// \details SHAKE is the base class for SHAKE128 and SHAKE258. +/// Library users should instantiate a derived class, and only use SHAKE +/// as a base class reference or pointer. +/// \sa Keccak, SHA3, SHAKE128, SHAKE256, +/// FIPS 202, +/// SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions +/// \since Crypto++ 8.1 +class SHAKE : public HashTransformation +{ +protected: + /// \brief Construct a SHAKE + /// \param digestSize the digest size, in bytes + /// \details SHAKE is the base class for SHAKE128 and SHAKE256. + /// Library users should instantiate a derived class, and only use SHAKE + /// 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++ 8.1 + SHAKE(unsigned int digestSize) : m_digestSize(digestSize) {Restart();} + +public: + unsigned int DigestSize() const {return m_digestSize;} + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + void Update(const byte *input, size_t length); + void Restart(); + void TruncatedFinal(byte *hash, size_t size); + +protected: + inline unsigned int r() const {return BlockSize();} + + // SHAKE-128 and SHAKE-256 effectively allow unlimited + // output length. However, we use an unsigned int so + // we are limited in practice to UINT_MAX. + void ThrowIfInvalidTruncatedSize(size_t size) const; + + FixedSizeSecBlock m_state; + unsigned int m_digestSize, m_counter; +}; + +/// \brief SHAKE message digest template +/// \tparam T_Strength the strength of the digest +/// \since Crypto++ 8.1 +template +class SHAKE_Final : public SHAKE +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE = (T_Strength == 128 ? 32 : 64)); + CRYPTOPP_CONSTANT(BLOCKSIZE = (T_Strength == 128 ? 1344/8 : 1088/8)); + static std::string StaticAlgorithmName() + { return "SHAKE-" + IntToString(T_Strength); } + + /// \brief Construct a SHAKE-X message digest + /// \details SHAKE128 and SHAKE256 don't need the output size in advance + /// because the output size does not affect the digest. TruncatedFinal + /// produces the correct digest for any output size. However, cSHAKE + /// requires the output size in advance because the algorithm uses + /// output size as a parameter to the hash function. + SHAKE_Final(unsigned int outputSize=DIGESTSIZE) : SHAKE(outputSize) {} + + /// \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 + /// to block size called rate expressed as r. + unsigned int BlockSize() const { return BLOCKSIZE; } + + std::string AlgorithmName() const { return StaticAlgorithmName(); } + +private: +#if !defined(__BORLANDC__) + // ensure there was no underflow in the math + CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); +#endif +}; + +/// \brief SHAKE128 message digest +/// \details The library provides byte oriented SHAKE128 using F1600. +/// FIPS 202 allows nearly unlimited output sizes, but Crypto++ limits +/// the output size to UINT_MAX due underlying data types. +/// \sa Keccak, SHA3, SHAKE256, +/// FIPS 202, +/// SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions +/// \since Crypto++ 8.1 +class SHAKE128 : public SHAKE_Final<128> +{ +public: + /// \brief Construct a SHAKE128 message digest + /// \details SHAKE128 and SHAKE256 don't need the output size in advance + /// because the output size does not affect the digest. TruncatedFinal + /// produces the correct digest for any output size. However, cSHAKE + /// requires the output size in advance because the algorithm uses + /// output size as a parameter to the hash function. + /// \since Crypto++ 8.1 + SHAKE128() {} + + /// \brief Construct a SHAKE128 message digest + /// \details SHAKE128 and SHAKE256 don't need the output size in advance + /// because the output size does not affect the digest. TruncatedFinal + /// produces the correct digest for any output size. However, cSHAKE + /// requires the output size in advance because the algorithm uses + /// output size as a parameter to the hash function. + /// \since Crypto++ 8.1 + SHAKE128(unsigned int outputSize) : SHAKE_Final<128>(outputSize) {} +}; + +/// \brief SHAKE256 message digest +/// \details The library provides byte oriented SHAKE256 using F1600. +/// FIPS 202 allows nearly unlimited output sizes, but Crypto++ limits +/// the output size to UINT_MAX due underlying data types. +/// \sa Keccak, SHA3, SHAKE128, +/// FIPS 202, +/// SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions +/// \since Crypto++ 8.1 +class SHAKE256 : public SHAKE_Final<256> +{ +public: + /// \brief Construct a SHAKE256 message digest + /// \details SHAKE128 and SHAKE256 don't need the output size in advance + /// because the output size does not affect the digest. TruncatedFinal + /// produces the correct digest for any output size. However, cSHAKE + /// requires the output size in advance because the algorithm uses + /// output size as a parameter to the hash function. + /// \since Crypto++ 8.1 + SHAKE256() {} + + /// \brief Construct a SHAKE256 message digest + /// \details SHAKE128 and SHAKE256 don't need the output size in advance + /// because the output size does not affect the digest. TruncatedFinal + /// produces the correct digest for any output size. However, cSHAKE + /// requires the output size in advance because the algorithm uses + /// output size as a parameter to the hash function. + /// \since Crypto++ 8.1 + SHAKE256(unsigned int outputSize) : SHAKE_Final<256>(outputSize) {} +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/shark.h b/third_party/cryptoppwin/include/cryptopp/shark.h new file mode 100644 index 00000000..8c73d26b --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/shark.h @@ -0,0 +1,77 @@ +// shark.h - originally written and placed in the public domain by Wei Dai + +/// \file shark.h +/// \brief Classes for the SHARK block cipher +/// \since Crypto++ 2.1 + +#ifndef CRYPTOPP_SHARK_H +#define CRYPTOPP_SHARK_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SHARK block cipher information +/// \since Crypto++ 2.1 +struct SHARK_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public VariableRounds<6, 2> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SHARK-E";} +}; + +/// \brief SHARK block cipher +/// SHARK-E +/// \since Crypto++ 2.1 +class SHARK : public SHARK_Info, public BlockCipherDocumentation +{ + /// \brief SHARK block cipher default operation + /// \since Crypto++ 2.1 + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶m); + + protected: + unsigned int m_rounds; + SecBlock m_roundKeys; + }; + + /// \brief SHARK block cipher encryption operation + /// \since Crypto++ 2.1 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + // used by Base to do key setup + void InitForKeySetup(); + + private: + static const byte sbox[256]; + static const word64 cbox[8][256]; + }; + + /// \brief SHARK block cipher decryption operation + /// \since Crypto++ 2.1 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + private: + static const byte sbox[256]; + static const word64 cbox[8][256]; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef SHARK::Encryption SHARKEncryption; +typedef SHARK::Decryption SHARKDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/simeck.h b/third_party/cryptoppwin/include/cryptopp/simeck.h new file mode 100644 index 00000000..7e76f70a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/simeck.h @@ -0,0 +1,162 @@ +// simeck.h - written and placed in the public domain by Gangqiang Yang and Jeffrey Walton. +// Based on "The Simeck Family of Lightweight Block Ciphers" by Gangqiang Yang, +// Bo Zhu, Valentin Suder, Mark D. Aagaard, and Guang Gong + +/// \file simeck.h +/// \brief Classes for the SIMECK block cipher +/// \sa SIMECK, +/// The Simeck +/// Family of Lightweight Block Ciphers +/// \since Crypto++ 8.0 + +#ifndef CRYPTOPP_SIMECK_H +#define CRYPTOPP_SIMECK_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SIMECK block cipher information +/// \since Crypto++ 8.0 +struct SIMECK32_Info : public FixedBlockSize<4>, public FixedKeyLength<8>, public FixedRounds<32> +{ + /// \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 "SIMECK-32"; + } +}; + +/// \brief SIMECK block cipher information +/// \since Crypto++ 8.0 +struct SIMECK64_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public FixedRounds<44> +{ + /// \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 "SIMECK-64"; + } +}; + +/// \brief SIMECK 32-bit block cipher +/// \details SIMECK32 provides 32-bit block size. The valid key size is 64-bit. +/// \note Crypto++ provides a byte oriented implementation +/// \sa SIMECK64, SIMECK, +/// The Simeck Family of +/// Lightweight Block Ciphers +/// \since Crypto++ 8.0 +class CRYPTOPP_NO_VTABLE SIMECK32 : public SIMECK32_Info, public BlockCipherDocumentation +{ +public: + /// \brief SIMECK block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 8.0 + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + std::string AlgorithmProvider() const; + + FixedSizeSecBlock m_rk; + mutable FixedSizeSecBlock m_t; + }; + + /// \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; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef SIMECK32::Encryption SIMECK32Encryption; +typedef SIMECK32::Decryption SIMECK32Decryption; + +/// \brief SIMECK 64-bit block cipher +/// \details SIMECK64 provides 64-bit block size. The valid key size is 128-bit. +/// \note Crypto++ provides a byte oriented implementation +/// \sa SIMECK32, SIMECK, +/// The Simeck Family of +/// Lightweight Block Ciphers +/// \since Crypto++ 8.0 +class CRYPTOPP_NO_VTABLE SIMECK64 : public SIMECK64_Info, public BlockCipherDocumentation +{ +public: + /// \brief SIMECK block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 8.0 + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + std::string AlgorithmProvider() const; + + FixedSizeSecBlock m_rk; + mutable FixedSizeSecBlock m_t; + }; + + /// \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_SIMECK_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_SIMECK_ADVANCED_PROCESS_BLOCKS + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef SIMECK64::Encryption SIMECK64Encryption; +typedef SIMECK64::Decryption SIMECK64Decryption; + +NAMESPACE_END + +#endif // CRYPTOPP_SIMECK_H diff --git a/third_party/cryptoppwin/include/cryptopp/simon.h b/third_party/cryptoppwin/include/cryptopp/simon.h new file mode 100644 index 00000000..35bb67f3 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/simon.h @@ -0,0 +1,206 @@ +// simon.h - written and placed in the public domain by Jeffrey Walton + +/// \file simon.h +/// \brief Classes for the Simon block cipher +/// \details Simon is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith, +/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers. +/// \sa The SIMON and SPECK Families of +/// Lightweight Block Ciphers, +/// The Simon and Speck GitHub and +/// SIMON on the Crypto++ wiki. +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_SIMON_H +#define CRYPTOPP_SIMON_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 || \ + CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8 || \ + CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 +# ifndef CRYPTOPP_DISABLE_SIMON_SIMD +# define CRYPTOPP_SIMON128_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_SIMON128_ADVANCED_PROCESS_BLOCKS +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SIMON block cipher information +/// \tparam L block size of the cipher, in bytes +/// \tparam D default key length, in bytes +/// \tparam N minimum key length, in bytes +/// \tparam M maximum key length, in bytes +/// \since Crypto++ 6.0 +template +struct SIMON_Info : public FixedBlockSize, VariableKeyLength +{ + /// \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(Keylength) + return "SIMON-" + IntToString(L*8); + } +}; + +/// \brief SIMON block cipher base class +/// \tparam W the word type +/// \details User code should use SIMON64 or SIMON128 +/// \sa SIMON64, SIMON128, SIMON on the Crypto++ wiki +/// \since Crypto++ 6.0 +template +struct SIMON_Base +{ + virtual ~SIMON_Base() {} + SIMON_Base() : m_kwords(0), m_rounds(0) {} + + typedef SecBlock > AlignedSecBlock; + mutable AlignedSecBlock m_wspace; // workspace + AlignedSecBlock m_rkeys; // round keys + unsigned int m_kwords; // number of key words + unsigned int m_rounds; // number of rounds +}; + +/// \brief SIMON 64-bit block cipher +/// \details Simon is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith, +/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers. +/// \details SIMON64 provides 64-bit block size. The valid key sizes are 96-bit and 128-bit. +/// \sa SIMON64, SIMON128, The SIMON and SIMON +/// Families of Lightweight Block Ciphers, +/// The Simon and Speck GitHub, SIMON on the +/// Crypto++ wiki +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE SIMON64 : public SIMON_Info<8, 12, 12, 16>, public BlockCipherDocumentation +{ +public: + /// \brief SIMON64 block cipher base implementation + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : protected SIMON_Base, public BlockCipherImpl > + { + public: + /// \brief The algorithm name + /// \return the algorithm name + /// \details AlgorithmName returns the algorithm's name as a + /// member function. + std::string AlgorithmName() const { + return StaticAlgorithmName() + (m_kwords == 0 ? "" : + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")"); + } + + std::string AlgorithmProvider() const; + + /// \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; + + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief SIMON64 encryption transformation + /// \details Enc provides the encryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief SIMON64 decryption transformation + /// \details Dec provides the decryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief SIMON 128-bit block cipher +/// \details Simon is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith, +/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers. +/// \details SIMON128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit. +/// \sa SIMON64, SIMON128, The SIMON and SIMON +/// Families of Lightweight Block Ciphers, +/// The Simon and Speck GitHub, SIMON on the +/// Crypto++ wiki +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE SIMON128 : public SIMON_Info<16, 16, 16, 32>, public BlockCipherDocumentation +{ +public: + /// \brief SIMON128 block cipher base implementation + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : protected SIMON_Base, public BlockCipherImpl > + { + public: + /// \brief The algorithm name + /// \return the algorithm name + /// \details AlgorithmName returns the algorithm's name as a + /// member function. + std::string AlgorithmName() const { + return StaticAlgorithmName() + (m_kwords == 0 ? "" : + "(" + IntToString(m_kwords*sizeof(word64)*8) + ")"); + } + + std::string AlgorithmProvider() const; + + /// \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; + + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief SIMON128 encryption transformation + /// \details Enc provides the encryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + + /// \brief SIMON128 decryption transformation + /// \details Dec provides the decryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_SIMON_H diff --git a/third_party/cryptoppwin/include/cryptopp/simple.h b/third_party/cryptoppwin/include/cryptopp/simple.h new file mode 100644 index 00000000..885c6781 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/simple.h @@ -0,0 +1,506 @@ +// simple.h - originally written and placed in the public domain by Wei Dai + +/// \file simple.h +/// \brief Classes providing basic library services. + +#ifndef CRYPTOPP_SIMPLE_H +#define CRYPTOPP_SIMPLE_H + +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4127 4189) +#endif + +#include "cryptlib.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Base class for identifying algorithm +/// \tparam BASE base class from which to derive +/// \tparam DERIVED class which to clone +template +class CRYPTOPP_NO_VTABLE ClonableImpl : public BASE +{ +public: + /// \brief Create a copy of this object + /// \return a copy of this object + /// \details The caller is responsible for freeing the object. + Clonable * Clone() const {return new DERIVED(*static_cast(this));} +}; + +/// \brief Base class information +/// \tparam BASE an Algorithm derived class +/// \tparam ALGORITHM_INFO an Algorithm derived class +/// \details AlgorithmImpl provides StaticAlgorithmName from the template parameter BASE +template +class CRYPTOPP_NO_VTABLE AlgorithmImpl : public BASE +{ +public: + /// \brief The algorithm name + /// \return the algorithm name + /// \details StaticAlgorithmName returns the algorithm's name as a static member function. + /// The name is taken from information provided by BASE. + static std::string CRYPTOPP_API StaticAlgorithmName() {return ALGORITHM_INFO::StaticAlgorithmName();} + /// \brief The algorithm name + /// \return the algorithm name + /// \details AlgorithmName returns the algorithm's name as a member function. + /// The name is acquired by calling StaticAlgorithmName. + std::string AlgorithmName() const {return ALGORITHM_INFO::StaticAlgorithmName();} +}; + +/// \brief Exception thrown when an invalid key length is encountered +class CRYPTOPP_DLL InvalidKeyLength : public InvalidArgument +{ +public: + /// \brief Construct an InvalidKeyLength + /// \param algorithm the Algorithm associated with the exception + /// \param length the key size associated with the exception + explicit InvalidKeyLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid key length") {} +}; + +/// \brief Exception thrown when an invalid number of rounds is encountered +class CRYPTOPP_DLL InvalidRounds : public InvalidArgument +{ +public: + /// \brief Construct an InvalidRounds + /// \param algorithm the Algorithm associated with the exception + /// \param rounds the number of rounds associated with the exception + explicit InvalidRounds(const std::string &algorithm, unsigned int rounds) : InvalidArgument(algorithm + ": " + IntToString(rounds) + " is not a valid number of rounds") {} +}; + +/// \brief Exception thrown when an invalid block size is encountered +class CRYPTOPP_DLL InvalidBlockSize : public InvalidArgument +{ +public: + /// \brief Construct an InvalidBlockSize + /// \param algorithm the Algorithm associated with the exception + /// \param length the block size associated with the exception + explicit InvalidBlockSize(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid block size") {} +}; + +/// \brief Exception thrown when an invalid derived key length is encountered +class CRYPTOPP_DLL InvalidDerivedKeyLength : public InvalidArgument +{ +public: + /// \brief Construct an InvalidDerivedKeyLength + /// \param algorithm the Algorithm associated with the exception + /// \param length the size associated with the exception + explicit InvalidDerivedKeyLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid derived key length") {} +}; + +/// \brief Exception thrown when an invalid personalization string length is encountered +class CRYPTOPP_DLL InvalidPersonalizationLength : public InvalidArgument +{ +public: + /// \brief Construct an InvalidPersonalizationLength + /// \param algorithm the Algorithm associated with the exception + /// \param length the personalization size associated with the exception + explicit InvalidPersonalizationLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid salt length") {} +}; + +/// \brief Exception thrown when an invalid salt length is encountered +class CRYPTOPP_DLL InvalidSaltLength : public InvalidArgument +{ +public: + /// \brief Construct an InvalidSaltLength + /// \param algorithm the Algorithm associated with the exception + /// \param length the salt size associated with the exception + explicit InvalidSaltLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid salt length") {} +}; + +// ***************************** + +/// \brief Base class for bufferless filters +/// \tparam T the class or type +template +class CRYPTOPP_NO_VTABLE Bufferless : public T +{ +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 + /// \note hardFlush must be used with care + bool IsolatedFlush(bool hardFlush, bool blocking) + {CRYPTOPP_UNUSED(hardFlush); CRYPTOPP_UNUSED(blocking); return false;} +}; + +/// \brief Base class for unflushable filters +/// \tparam T the class or type +template +class CRYPTOPP_NO_VTABLE Unflushable : public T +{ +public: + /// \brief Flush buffered input and/or output, with signal propagation + /// \param completeFlush is used to indicate whether all data should be flushed + /// \param propagation the number of attached transformations the Flush() + /// signal should be passed + /// \param blocking specifies whether the object should block when processing + /// input + /// \details propagation count includes this object. Setting propagation to + /// 1 means this object only. Setting propagation to -1 + /// 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. + /// \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. + bool Flush(bool completeFlush, int propagation=-1, bool blocking=true) + {return ChannelFlush(DEFAULT_CHANNEL, completeFlush, propagation, blocking);} + + /// \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 + /// \note hardFlush must be used with care + bool IsolatedFlush(bool hardFlush, bool blocking) + {CRYPTOPP_UNUSED(hardFlush); CRYPTOPP_UNUSED(blocking); CRYPTOPP_ASSERT(false); return false;} + + /// \brief Flush buffered input and/or output on a channel + /// \param channel the channel to flush the data + /// \param hardFlush is used to indicate whether all data should be flushed + /// \param propagation the number of attached transformations the ChannelFlush() + /// signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true of the Flush was successful + /// \details propagation count includes this object. Setting propagation to + /// 1 means this object only. Setting propagation to -1 means + /// unlimited propagation. + bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) + { + if (hardFlush && !InputBufferIsEmpty()) + throw CannotFlush("Unflushable: this object has buffered input that cannot be flushed"); + else + { + BufferedTransformation *attached = this->AttachedTransformation(); + return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false; + } + } + +protected: + virtual bool InputBufferIsEmpty() const {return false;} +}; + +/// \brief Base class for input rejecting filters +/// \tparam T the class or type +/// \details T should be a BufferedTransformation derived class +template +class CRYPTOPP_NO_VTABLE InputRejecting : public T +{ +public: + struct InputRejected : public NotImplemented + {InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}}; + + /// \name INPUT + //@{ + + /// \brief Input a byte array for processing + /// \param inString the byte array to process + /// \param length the size of the string, in bytes + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one + /// \param blocking specifies whether the object should block when processing input + /// \throw InputRejected + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + /// \details Internally, the default implementation throws InputRejected. + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + {CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); throw InputRejected();} + //@} + + /// \name SIGNALS + //@{ + + /// \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 + /// \note hardFlush must be used with care + bool IsolatedFlush(bool hardFlush, bool blocking) + {CRYPTOPP_UNUSED(hardFlush); CRYPTOPP_UNUSED(blocking); return false;} + + /// \brief Marks the end of a series of messages, without signal propagation + /// \param blocking specifies whether the object should block when completing the processing on + /// the current series of messages + /// \return true if the message was successful, false otherwise + bool IsolatedMessageSeriesEnd(bool blocking) + {CRYPTOPP_UNUSED(blocking); throw InputRejected();} + + /// \brief Input multiple bytes for processing on a channel. + /// \param channel the channel to process the data. + /// \param inString the byte buffer to process. + /// \param length the size of the string, in bytes. + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + size_t ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking) + {CRYPTOPP_UNUSED(channel); CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); + CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); throw InputRejected();} + + /// \brief Marks the end of a series of messages on a channel + /// \param channel the channel to signal the end of a series of messages + /// \param messageEnd the number of attached transformations the ChannelMessageSeriesEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true if the message 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. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + /// \note There should be a MessageEnd() immediately before MessageSeriesEnd(). + bool ChannelMessageSeriesEnd(const std::string& channel, int messageEnd, bool blocking) + {CRYPTOPP_UNUSED(channel); CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); throw InputRejected();} + //@} +}; + +/// \brief Interface for custom flush signals propagation +/// \tparam T BufferedTransformation derived class +template +class CRYPTOPP_NO_VTABLE CustomFlushPropagation : public T +{ +public: + /// \name SIGNALS + //@{ + + /// \brief Flush buffered input and/or output, with signal propagation + /// \param hardFlush is used to indicate whether all data should be flushed + /// \param propagation the number of attached transformations the Flush() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 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. + /// \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. + virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0; + + //@} + +private: + bool IsolatedFlush(bool hardFlush, bool blocking) + {CRYPTOPP_UNUSED(hardFlush); CRYPTOPP_UNUSED(blocking); CRYPTOPP_ASSERT(false); return false;} +}; + +/// \brief Interface for custom flush signals +/// \tparam T BufferedTransformation derived class +template +class CRYPTOPP_NO_VTABLE CustomSignalPropagation : public CustomFlushPropagation +{ +public: + /// \brief Initialize or reinitialize this object, with signal propagation + /// \param parameters a set of NameValuePairs to initialize or reinitialize this object + /// \param propagation the number of attached transformations the Initialize() signal should be passed + /// \details Initialize() is used to initialize or reinitialize an object using a variable number of + /// arbitrarily typed arguments. The function avoids the need for multiple constructors providing + /// all possible combintations of configurable parameters. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0; + +private: + void IsolatedInitialize(const NameValuePairs ¶meters) + {CRYPTOPP_UNUSED(parameters); CRYPTOPP_ASSERT(false);} +}; + +/// \brief Multiple channels support for custom signal processing +/// \tparam T the class or type +/// \details T should be a BufferedTransformation derived class +template +class CRYPTOPP_NO_VTABLE Multichannel : public CustomFlushPropagation +{ +public: + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) + {return this->ChannelFlush(DEFAULT_CHANNEL, hardFlush, propagation, blocking);} + + /// \brief Marks the end of a series of messages, with signal propagation + /// \param propagation the number of attached transformations the MessageSeriesEnd() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \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. + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + /// \note There should be a MessageEnd() immediately before MessageSeriesEnd(). + bool MessageSeriesEnd(int propagation=-1, bool blocking=true) + {return this->ChannelMessageSeriesEnd(DEFAULT_CHANNEL, propagation, blocking);} + + /// \brief Request space which can be written into by the caller + /// \param size the requested size of the buffer + /// \details The purpose of this method is to help avoid extra memory allocations. + /// \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made, + /// size is the requested size of the buffer. When the call returns, size is the size of + /// the array returned to the caller. + /// \details The base class implementation sets size to 0 and returns NULL. + /// \note Some objects, like ArraySink, cannot create a space because its fixed. In the case of + /// an ArraySink, the pointer to the array is returned and the size is remaining size. + byte * CreatePutSpace(size_t &size) + {return this->ChannelCreatePutSpace(DEFAULT_CHANNEL, size);} + + /// \brief Input multiple bytes for processing + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + /// \details Derived classes must implement Put2(). + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + {return this->ChannelPut2(DEFAULT_CHANNEL, inString, length, messageEnd, blocking);} + + /// \brief Input multiple bytes that may be modified by callee. + /// \param inString the byte buffer to process. + /// \param length the size of the string, in bytes. + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + /// \details Internally, PutModifiable2() calls Put2(). + size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) + {return this->ChannelPutModifiable2(DEFAULT_CHANNEL, inString, length, messageEnd, blocking);} + + // void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1) + // {PropagateMessageSeriesEnd(propagation, channel);} + + /// \brief Request space which can be written into by the caller + /// \param channel the channel to process the data + /// \param size the requested size of the buffer + /// \return a pointer to a memory block with length size + /// \details The purpose of this method is to help avoid extra memory allocations. + /// \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made, + /// size is the requested size of the buffer. When the call returns, size is the size of + /// the array returned to the caller. + /// \details The base class implementation sets size to 0 and returns NULL. + /// \note Some objects, like ArraySink(), cannot create a space because its fixed. In the case of + /// an ArraySink(), the pointer to the array is returned and the size is remaining size. + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) + {CRYPTOPP_UNUSED(channel); size = 0; return NULLPTR;} + + /// \brief Input multiple bytes that may be modified by callee on a channel + /// \param channel the channel to process the data. + /// \param inString the byte buffer to process + /// \param length the size of the string, in bytes + /// \return true if all bytes were processed, false otherwise. + bool ChannelPutModifiable(const std::string &channel, byte *inString, size_t length) + {this->ChannelPut(channel, inString, length); return false;} + + /// \brief Input multiple bytes for processing on a channel. + /// \param channel the channel to process the data. + /// \param begin the byte buffer to process. + /// \param length the size of the string, in bytes. + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one. + /// \param blocking specifies whether the object should block when processing input. + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) =0; + + /// \brief Input multiple bytes that may be modified by callee on a channel + /// \param channel the channel to process the data + /// \param begin the byte buffer to process + /// \param length the size of the string, in bytes + /// \param messageEnd means how many filters to signal MessageEnd() to, including this one + /// \param blocking specifies whether the object should block when processing input + /// \return the number of bytes that remain to be processed (i.e., bytes not processed) + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) + {return ChannelPut2(channel, begin, length, messageEnd, blocking);} + + /// \brief Flush buffered input and/or output on a channel + /// \param channel the channel to flush the data + /// \param hardFlush is used to indicate whether all data should be flushed + /// \param propagation the number of attached transformations the ChannelFlush() signal should be passed + /// \param blocking specifies whether the object should block when processing input + /// \return true of the Flush was successful + /// \details propagation count includes this object. Setting propagation to 1 means this + /// object only. Setting propagation to -1 means unlimited propagation. + virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) =0; +}; + +/// \brief Provides auto signaling support +/// \tparam T BufferedTransformation derived class +template +class CRYPTOPP_NO_VTABLE AutoSignaling : public T +{ +public: + /// \brief Construct an AutoSignaling + /// \param propagation the propagation count + AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {} + + /// \brief Set propagation of automatically generated and transferred signals + /// \param propagation then new value + /// \details Setting propagation to 0 means do not automatically generate signals. Setting + /// propagation to -1 means unlimited propagation. + void SetAutoSignalPropagation(int propagation) + {m_autoSignalPropagation = propagation;} + + /// \brief Retrieve automatic signal propagation value + /// \return the number of attached transformations the signal is propagated to. 0 indicates + /// the signal is only witnessed by this object + int GetAutoSignalPropagation() const + {return m_autoSignalPropagation;} + +private: + int m_autoSignalPropagation; +}; + +/// \brief Acts as a Source for pre-existing, static data +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Store : public AutoSignaling > +{ +public: + /// \brief Construct a Store + Store() : m_messageEnd(false) {} + + void IsolatedInitialize(const NameValuePairs ¶meters) + { + m_messageEnd = false; + StoreInitialize(parameters); + } + + unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;} + bool GetNextMessage(); + unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; + +protected: + virtual void StoreInitialize(const NameValuePairs ¶meters) =0; + + bool m_messageEnd; +}; + +/// \brief Implementation of BufferedTransformation's attachment interface +/// \details Sink 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 A Sink does not produce any retrievable output. +/// \details See the discussion of BufferedTransformation in cryptlib.h for +/// more details. +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Sink : public BufferedTransformation +{ +public: + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) + {CRYPTOPP_UNUSED(target); CRYPTOPP_UNUSED(transferBytes); CRYPTOPP_UNUSED(channel); CRYPTOPP_UNUSED(blocking); transferBytes = 0; return 0;} + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const + {CRYPTOPP_UNUSED(target); CRYPTOPP_UNUSED(begin); CRYPTOPP_UNUSED(end); CRYPTOPP_UNUSED(channel); CRYPTOPP_UNUSED(blocking); return 0;} +}; + +/// \brief Acts as an input discarding Filter or Sink +/// \details The BitBucket discards all input and returns 0 to the caller +/// to indicate all data was processed. +class CRYPTOPP_DLL BitBucket : public Bufferless +{ +public: + std::string AlgorithmName() const {return "BitBucket";} + void IsolatedInitialize(const NameValuePairs ¶ms) + {CRYPTOPP_UNUSED(params);} + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + {CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking); return 0;} +}; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/siphash.h b/third_party/cryptoppwin/include/cryptopp/siphash.h new file mode 100644 index 00000000..5eb53216 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/siphash.h @@ -0,0 +1,314 @@ +// siphash.h - written and placed in public domain by Jeffrey Walton. + +/// \file siphash.h +/// \brief Classes for SipHash message authentication code +/// \details SipHash computes a 64-bit or 128-bit message authentication code from a variable-length +/// message and 128-bit secret key. It was designed to be efficient even for short inputs, with +/// performance comparable to non-cryptographic hash functions. +/// \details To create a SipHash-2-4 object with a 64-bit MAC use code similar to the following. +///
  SecByteBlock key(16);
+///   prng.GenerateBlock(key, key.size());
+///
+///   SipHash<2,4,false> hash(key, key.size());
+///   hash.Update(...);
+///   hash.Final(...);
+/// \details To create a SipHash-2-4 object with a 128-bit MAC use code similar to the following. +///
  SecByteBlock key(16);
+///   prng.GenerateBlock(key, key.size());
+///
+///   SipHash<2,4,true> hash(key, key.size());
+///   hash.Update(...);
+///   hash.Final(...);
+/// \sa Jean-Philippe Aumasson and Daniel J. Bernstein SipHash: +/// a fast short-input PRF +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_SIPHASH_H +#define CRYPTOPP_SIPHASH_H + +#include "cryptlib.h" +#include "secblock.h" +#include "seckey.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SipHash message authentication code information +/// \tparam T_128bit flag indicating 128-bit (true) versus 64-bit (false) digest size +template +class SipHash_Info : public FixedKeyLength<16> +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SipHash";} + CRYPTOPP_CONSTANT(DIGESTSIZE = (T_128bit ? 16 : 8)); +}; + +/// \brief SipHash message authentication code base class +/// \tparam C the number of compression rounds +/// \tparam D the number of finalization rounds +/// \tparam T_128bit flag indicating 128-bit (true) versus 64-bit (false) digest size +template +class SipHash_Base : public MessageAuthenticationCode, public SipHash_Info +{ +public: + static std::string StaticAlgorithmName() { + return std::string(SipHash_Info::StaticAlgorithmName())+"-"+IntToString(C)+"-"+IntToString(D); + } + + virtual ~SipHash_Base() {} + + SipHash_Base() : m_idx(0) {} + + virtual unsigned int DigestSize() const + {return SipHash_Info::DIGESTSIZE;} + virtual size_t MinKeyLength() const + {return SipHash_Info::MIN_KEYLENGTH;} + virtual size_t MaxKeyLength() const + {return SipHash_Info::MAX_KEYLENGTH;} + virtual size_t DefaultKeyLength() const + {return SipHash_Info::DEFAULT_KEYLENGTH;} + virtual size_t GetValidKeyLength(size_t keylength) const + {CRYPTOPP_UNUSED(keylength); return SipHash_Info::DEFAULT_KEYLENGTH;} + virtual IV_Requirement IVRequirement() const + {return SimpleKeyingInterface::NOT_RESYNCHRONIZABLE;} + virtual unsigned int IVSize() const + {return 0;} + virtual unsigned int OptimalBlockSize() const + {return sizeof(word64);} + virtual unsigned int OptimalDataAlignment () const + {return GetAlignmentOf();} + + virtual void Update(const byte *input, size_t length); + virtual void TruncatedFinal(byte *digest, size_t digestSize); + +protected: + + virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + virtual void Restart(); + + inline void SIPROUND() + { + m_v[0] += m_v[1]; + m_v[1] = rotlConstant<13>(m_v[1]); + m_v[1] ^= m_v[0]; + m_v[0] = rotlConstant<32>(m_v[0]); + m_v[2] += m_v[3]; + m_v[3] = rotlConstant<16>(m_v[3]); + m_v[3] ^= m_v[2]; + m_v[0] += m_v[3]; + m_v[3] = rotlConstant<21>(m_v[3]); + m_v[3] ^= m_v[0]; + m_v[2] += m_v[1]; + m_v[1] = rotlConstant<17>(m_v[1]); + m_v[1] ^= m_v[2]; + m_v[2] = rotlConstant<32>(m_v[2]); + } + +private: + FixedSizeSecBlock m_v; + FixedSizeSecBlock m_k; + FixedSizeSecBlock m_b; + + // Tail bytes + FixedSizeSecBlock m_acc; + size_t m_idx; +}; + +/// \brief SipHash message authentication code +/// \tparam C the number of compression rounds +/// \tparam D the number of finalization rounds +/// \tparam T_128bit flag indicating 128-bit (true) versus 64-bit (false) digest size +/// \details SipHash computes a 64-bit or 128-bit message authentication code from a variable-length +/// message and 128-bit secret key. It was designed to be efficient even for short inputs, with +/// performance comparable to non-cryptographic hash functions. +/// \details To create a SipHash-2-4 object with a 64-bit MAC use code similar to the following. +///
  SecByteBlock key(16);
+///   prng.GenerateBlock(key, key.size());
+///
+///   SipHash<2,4,false> hash(key, key.size());
+///   hash.Update(...);
+///   hash.Final(...);
+/// \details To create a SipHash-2-4 object with a 128-bit MAC use code similar to the following. +///
  SecByteBlock key(16);
+///   prng.GenerateBlock(key, key.size());
+///
+///   SipHash<2,4,true> hash(key, key.size());
+///   hash.Update(...);
+///   hash.Final(...);
+/// \sa Jean-Philippe Aumasson and Daniel J. Bernstein SipHash: +/// a fast short-input PRF +/// \since Crypto++ 6.0 +template +class SipHash : public SipHash_Base +{ +public: + /// \brief Create a SipHash + SipHash() + {this->UncheckedSetKey(NULLPTR, 0, g_nullNameValuePairs);} + /// \brief Create a SipHash + /// \param key a byte array used to key the cipher + /// \param length the size of the byte array, in bytes + SipHash(const byte *key, unsigned int length) + {this->ThrowIfInvalidKeyLength(length); + this->UncheckedSetKey(key, length, g_nullNameValuePairs);} +}; + +template +void SipHash_Base::Update(const byte *input, size_t length) +{ + CRYPTOPP_ASSERT((input && length) || !length); + if (!length) return; + + if (m_idx) + { + size_t head = STDMIN(size_t(8U-m_idx), length); + std::memcpy(m_acc+m_idx, input, head); + m_idx += head; input += head; length -= head; + + if (m_idx == 8) + { + word64 m = GetWord(true, LITTLE_ENDIAN_ORDER, m_acc); + m_v[3] ^= m; + for (unsigned int i = 0; i < C; ++i) + SIPROUND(); + + m_v[0] ^= m; + m_b[0] += 8; + + m_idx = 0; + } + } + + while (length >= 8) + { + word64 m = GetWord(false, LITTLE_ENDIAN_ORDER, input); + m_v[3] ^= m; + for (unsigned int i = 0; i < C; ++i) + SIPROUND(); + + m_v[0] ^= m; + m_b[0] += 8; + + input += 8; + length -= 8; + } + + CRYPTOPP_ASSERT(length < 8); + size_t tail = length % 8; + if (tail) + { + std::memcpy(m_acc+m_idx, input, tail); + m_idx += tail; + } +} + +template +void SipHash_Base::TruncatedFinal(byte *digest, size_t digestSize) +{ + CRYPTOPP_ASSERT(digest); // Pointer is valid + + ThrowIfInvalidTruncatedSize(digestSize); + + // The high octet holds length and is digested mod 256 + m_b[0] += m_idx; m_b[0] <<= 56U; + switch (m_idx) + { + case 7: + m_b[0] |= ((word64)m_acc[6]) << 48; + // fall through + case 6: + m_b[0] |= ((word64)m_acc[5]) << 40; + // fall through + case 5: + m_b[0] |= ((word64)m_acc[4]) << 32; + // fall through + case 4: + m_b[0] |= ((word64)m_acc[3]) << 24; + // fall through + case 3: + m_b[0] |= ((word64)m_acc[2]) << 16; + // fall through + case 2: + m_b[0] |= ((word64)m_acc[1]) << 8; + // fall through + case 1: + m_b[0] |= ((word64)m_acc[0]); + // fall through + case 0: + break; + } + + m_v[3] ^= m_b[0]; + + for (unsigned int i=0; i::DIGESTSIZE)); + Restart(); +} + +template +void SipHash_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + if (key && length) + { + m_k[0] = GetWord(false, LITTLE_ENDIAN_ORDER, key); + m_k[1] = GetWord(false, LITTLE_ENDIAN_ORDER, key+8); + } + else + { + // Avoid Coverity finding + m_k[0] = m_k[1] = 0; + } + Restart(); +} + +template +void SipHash_Base::Restart () +{ + m_v[0] = W64LIT(0x736f6d6570736575); + m_v[1] = W64LIT(0x646f72616e646f6d); + m_v[2] = W64LIT(0x6c7967656e657261); + m_v[3] = W64LIT(0x7465646279746573); + + m_v[3] ^= m_k[1]; + m_v[2] ^= m_k[0]; + m_v[1] ^= m_k[1]; + m_v[0] ^= m_k[0]; + + if (T_128bit) + { + m_v[1] ^= 0xee; + } + + m_idx = 0; + m_b[0] = 0; +} + +NAMESPACE_END + +#endif // CRYPTOPP_SIPHASH_H diff --git a/third_party/cryptoppwin/include/cryptopp/skipjack.h b/third_party/cryptoppwin/include/cryptopp/skipjack.h new file mode 100644 index 00000000..96fdaf40 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/skipjack.h @@ -0,0 +1,80 @@ +// skipjack.h - originally written and placed in the public domain by Wei Dai + +/// \file skipjack.h +/// \brief Classes for the SKIPJACK block cipher +/// \details The Crypto++ implementation conforms to SKIPJACK and KEA +/// Algorithm Specifications published by NIST in May 1998. The library passes +/// known answer tests available in NIST SP800-17, Table 6, pp. 140-42. +/// \sa SKIPJACK +/// and KEA Algorithm Specifications (May 1998), +/// SKIPJACK on the +// Crypto++ wiki + +#ifndef CRYPTOPP_SKIPJACK_H +#define CRYPTOPP_SKIPJACK_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SKIPJACK block cipher information +struct SKIPJACK_Info : public FixedBlockSize<8>, public FixedKeyLength<10> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "SKIPJACK";} +}; + +/// \brief SKIPJACK block cipher +/// \details The Crypto++ implementation conforms to SKIPJACK and KEA +/// Algorithm Specifications published by NIST in May 1998. The library passes +/// known answer tests available in NIST SP800-17, Table 6, pp. 140-42. +/// \sa SKIPJACK +/// and KEA Algorithm Specifications (May 1998), +/// SKIPJACK on the +/// Crypto++ wiki +class SKIPJACK : public SKIPJACK_Info, public BlockCipherDocumentation +{ + /// \brief SKIPJACK block cipher default operation + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + protected: + static const byte fTable[256]; + + FixedSizeSecBlock tab; + }; + + /// \brief SKIPJACK block cipher encryption operation + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + private: + static const byte Se[256]; + static const word32 Te[4][256]; + }; + + /// \brief SKIPJACK block cipher decryption operation + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + private: + static const byte Sd[256]; + static const word32 Td[4][256]; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef SKIPJACK::Encryption SKIPJACKEncryption; +typedef SKIPJACK::Decryption SKIPJACKDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/sm3.h b/third_party/cryptoppwin/include/cryptopp/sm3.h new file mode 100644 index 00000000..fefcfec4 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sm3.h @@ -0,0 +1,61 @@ +// sm3.h - written and placed in the public domain by Jeffrey Walton and Han Lulu +// Based on the specification provided by Sean Shen and Xiaodong Lee. +// Based on code by Krzysztof Kwiatkowski and Jack Lloyd. +// Also see https://tools.ietf.org/html/draft-shen-sm3-hash. + +/// \file sm3.h +/// \brief Classes for the SM3 hash function +/// \details SM3 is a hash function designed by Xiaoyun Wang, et al. The hash is part of the +/// Chinese State Cryptography Administration portfolio. +/// \sa SM3 Hash Function and +/// Reference implementation using OpenSSL. +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_SM3_H +#define CRYPTOPP_SM3_H + +#include "config.h" +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SM3 hash function +/// \details SM3 is a hash function designed by Xiaoyun Wang, et al. The hash is part of the +/// Chinese State Cryptography Administration portfolio. +/// \sa SM3 Hash Function +/// \since Crypto++ 6.0 +class SM3 : public IteratedHashWithStaticTransform +{ +public: + /// \brief Initialize state array + /// \param state the state of the hash + /// \details InitState sets a state array to SM3 initial values + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState() and Transform(). External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + static void InitState(HashWordType *state); + + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + /// \details Transform() operates the hash on data. When the call is invoked + /// digest holds initial or current state. Upon return digest holds + /// the hash or updated state. + /// \details Hashes which derive from IteratedHashWithStaticTransform provide static + /// member functions InitState() and Transform(). External classes, like SEAL and MDC, + /// can initialize state with a user provided key and operate the hash on the data + /// with the user supplied state. + static void Transform(HashWordType *digest, const HashWordType *data); + + /// \brief The algorithm name + /// \return C-style string "SM3" + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "SM3"; } + +protected: + size_t HashMultipleBlocks(const HashWordType *input, size_t length); +}; + +NAMESPACE_END + +#endif // CRYPTOPP_SM3_H diff --git a/third_party/cryptoppwin/include/cryptopp/sm4.h b/third_party/cryptoppwin/include/cryptopp/sm4.h new file mode 100644 index 00000000..dc41f732 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sm4.h @@ -0,0 +1,96 @@ +// sm4.h - written and placed in the public domain by Jeffrey Walton and Han Lulu + +/// \file sm4.h +/// \brief Classes for the SM4 block cipher +/// \details SM4 is a block cipher designed by Xiaoyun Wang, et al. The block cipher is part of the +/// Chinese State Cryptography Administration portfolio. The cipher was formerly known as SMS4. +/// \details SM4 encryption is accelerated on machines with AES-NI. Decryption is not accelerated because +/// it is not profitable. Thanks to Markku-Juhani Olavi Saarinen for help and the code. +/// \sa SMS4 Encryption Algorithm for Wireless Networks, +/// Reference implementation using OpenSSL and +/// Markku-Juhani Olavi Saarinen GitHub. +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_SM4_H +#define CRYPTOPP_SM4_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86) +# ifndef CRYPTOPP_DISABLE_SM4_SIMD +# define CRYPTOPP_SM4_ADVANCED_PROCESS_BLOCKS 1 +# endif +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SM4 block cipher information +/// \since Crypto++ 6.0 +struct SM4_Info : public FixedBlockSize<16>, FixedKeyLength<16> +{ + static const std::string StaticAlgorithmName() + { + return "SM4"; + } +}; + +/// \brief Classes for the SM4 block cipher +/// \details SM4 is a block cipher designed by Xiaoyun Wang, et al. The block cipher is part of the +/// Chinese State Cryptography Administration portfolio. The cipher was formerly known as SMS4. +/// \sa SMS4 Encryption Algorithm for Wireless Networks +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE SM4 : public SM4_Info, public BlockCipherDocumentation +{ +public: + /// \brief SM4 block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + + SecBlock > m_rkeys; + mutable SecBlock > m_wspace; + }; + + /// \brief Encryption transformation + /// \details Enc provides implementation for encryption transformation. All key + /// sizes are supported. + /// \details SM4 encryption is accelerated on machines with AES-NI. Decryption is + /// not accelerated because it is not profitable. Thanks to Markku-Juhani Olavi + /// Saarinen. + /// \since Crypto++ 6.0, AESNI encryption since Crypto++ 8.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + std::string AlgorithmProvider() const; + protected: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_SM4_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 + /// sizes are supported. + /// \details SM4 encryption is accelerated on machines with AES-NI. Decryption is + /// not accelerated because it is not profitable. Thanks to Markku-Juhani Olavi + /// Saarinen. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + protected: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_SM4_H diff --git a/third_party/cryptoppwin/include/cryptopp/smartptr.h b/third_party/cryptoppwin/include/cryptopp/smartptr.h new file mode 100644 index 00000000..4e16a7fe --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/smartptr.h @@ -0,0 +1,257 @@ +// smartptr.h - originally written and placed in the public domain by Wei Dai + +/// \file smartptr.h +/// \brief Classes for automatic resource management + +#ifndef CRYPTOPP_SMARTPTR_H +#define CRYPTOPP_SMARTPTR_H + +#include "config.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Manages resources for a single object +/// \tparam T class or type +/// \details \p simple_ptr is used frequently in the library to manage resources and +/// ensure cleanup under the RAII pattern (Resource Acquisition Is Initialization). +template class simple_ptr +{ +public: + simple_ptr(T *p = NULLPTR) : m_p(p) {} + ~simple_ptr() + { + delete m_p; + m_p = NULLPTR; + } + + T *m_p; +}; + +/// \brief Pointer that overloads operator -> +/// \tparam T class or type +/// \details member_ptr is used frequently in the library to avoid the issues related to +/// std::auto_ptr in C++11 (deprecated) and std::unique_ptr in C++03 (non-existent). +/// \bug Issue 48: "Use of auto_ptr +/// causes dirty compile under C++11" +template class member_ptr +{ +public: + explicit member_ptr(T *p = NULLPTR) : m_p(p) {} + + ~member_ptr(); + + const T& operator*() const { return *m_p; } + T& operator*() { return *m_p; } + + const T* operator->() const { return m_p; } + T* operator->() { return m_p; } + + const T* get() const { return m_p; } + T* get() { return m_p; } + + T* release() + { + T *old_p = m_p; + m_p = NULLPTR; + return old_p; + } + + void reset(T *p = NULLPTR); + +protected: + member_ptr(const member_ptr& rhs); // copy not allowed + void operator=(const member_ptr& rhs); // assignment not allowed + + T *m_p; +}; + +template member_ptr::~member_ptr() {delete m_p;} +template void member_ptr::reset(T *p) {delete m_p; m_p = p;} + +// ******************************************************** + +/// \brief Value pointer +/// \tparam T class or type +template class value_ptr : public member_ptr +{ +public: + value_ptr(const T &obj) : member_ptr(new T(obj)) {} + value_ptr(T *p = NULLPTR) : member_ptr(p) {} + value_ptr(const value_ptr& rhs) + : member_ptr(rhs.m_p ? new T(*rhs.m_p) : NULLPTR) {} + + value_ptr& operator=(const value_ptr& rhs); + bool operator==(const value_ptr& rhs) + { + return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p); + } +}; + +template value_ptr& value_ptr::operator=(const value_ptr& rhs) +{ + T *old_p = this->m_p; + this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULLPTR; + delete old_p; + return *this; +} + +// ******************************************************** + +/// \brief A pointer which can be copied and cloned +/// \tparam T class or type +/// \details \p T should adhere to the \p Clonable interface +template class clonable_ptr : public member_ptr +{ +public: + clonable_ptr(const T &obj) : member_ptr(obj.Clone()) {} + clonable_ptr(T *p = NULLPTR) : member_ptr(p) {} + clonable_ptr(const clonable_ptr& rhs) + : member_ptr(rhs.m_p ? rhs.m_p->Clone() : NULLPTR) {} + + clonable_ptr& operator=(const clonable_ptr& rhs); +}; + +template clonable_ptr& clonable_ptr::operator=(const clonable_ptr& rhs) +{ + T *old_p = this->m_p; + this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULLPTR; + delete old_p; + return *this; +} + +// ******************************************************** + +/// \brief Reference counted pointer +/// \tparam T class or type +/// \details users should declare \p m_referenceCount as std::atomic +/// (or similar) under C++ 11 +template class counted_ptr +{ +public: + explicit counted_ptr(T *p = NULLPTR); + counted_ptr(const T &r) : m_p(0) {attach(r);} + counted_ptr(const counted_ptr& rhs); + + ~counted_ptr(); + + const T& operator*() const { return *m_p; } + T& operator*() { return *m_p; } + + const T* operator->() const { return m_p; } + T* operator->() { return get(); } + + const T* get() const { return m_p; } + T* get(); + + void attach(const T &p); + + counted_ptr & operator=(const counted_ptr& rhs); + +private: + T *m_p; +}; + +template counted_ptr::counted_ptr(T *p) + : m_p(p) +{ + if (m_p) + m_p->m_referenceCount = 1; +} + +template counted_ptr::counted_ptr(const counted_ptr& rhs) + : m_p(rhs.m_p) +{ + if (m_p) + m_p->m_referenceCount++; +} + +template counted_ptr::~counted_ptr() +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; +} + +template void counted_ptr::attach(const T &r) +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; + if (r.m_referenceCount == 0) + { + m_p = r.clone(); + m_p->m_referenceCount = 1; + } + else + { + m_p = const_cast(&r); + m_p->m_referenceCount++; + } +} + +template T* counted_ptr::get() +{ + if (m_p && m_p->m_referenceCount > 1) + { + T *temp = m_p->clone(); + m_p->m_referenceCount--; + m_p = temp; + m_p->m_referenceCount = 1; + } + return m_p; +} + +template counted_ptr & counted_ptr::operator=(const counted_ptr& rhs) +{ + if (m_p != rhs.m_p) + { + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; + m_p = rhs.m_p; + if (m_p) + m_p->m_referenceCount++; + } + return *this; +} + +// ******************************************************** + +/// \brief Manages resources for an array of objects +/// \tparam T class or type +template class vector_member_ptrs +{ +public: + /// Construct an array of \p T + /// \param size the size of the array, in elements + /// \details If \p T is a Plain Old Dataype (POD), then the array is uninitialized. + vector_member_ptrs(size_t size=0) + : m_size(size), m_ptr(new member_ptr[size]) {} + ~vector_member_ptrs() + {delete [] this->m_ptr;} + + member_ptr& operator[](size_t index) + {CRYPTOPP_ASSERT(indexm_size); return this->m_ptr[index];} + const member_ptr& operator[](size_t index) const + {CRYPTOPP_ASSERT(indexm_size); return this->m_ptr[index];} + + size_t size() const {return this->m_size;} + void resize(size_t newSize) + { + member_ptr *newPtr = new member_ptr[newSize]; + for (size_t i=0; im_size && im_ptr[i].release()); + delete [] this->m_ptr; + this->m_size = newSize; + this->m_ptr = newPtr; + } + +private: + vector_member_ptrs(const vector_member_ptrs &c); // copy not allowed + void operator=(const vector_member_ptrs &x); // assignment not allowed + + size_t m_size; + member_ptr *m_ptr; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/sosemanuk.h b/third_party/cryptoppwin/include/cryptopp/sosemanuk.h new file mode 100644 index 00000000..fc1a1bb7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/sosemanuk.h @@ -0,0 +1,62 @@ +// sosemanuk.h - originally written and placed in the public domain by Wei Dai + +/// \file sosemanuk.h +/// \brief Classes for Sosemanuk stream cipher +/// \since Crypto++ 5.5 + +#ifndef CRYPTOPP_SOSEMANUK_H +#define CRYPTOPP_SOSEMANUK_H + +#include "strciphr.h" +#include "secblock.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_SOSEMANUK_ASM 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Sosemanuk stream cipher information +/// \since Crypto++ 5.5 +struct SosemanukInfo : public VariableKeyLength<16, 1, 32, 1, SimpleKeyingInterface::UNIQUE_IV, 16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Sosemanuk";} +}; + +/// \brief Sosemanuk stream cipher implementation +/// \since Crypto++ 5.5 +class SosemanukPolicy : public AdditiveCipherConcretePolicy, public SosemanukInfo +{ +protected: + std::string AlgorithmProvider() const; + void CipherSetKey(const NameValuePairs ¶ms, 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;} +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) + unsigned int GetAlignment() const; + unsigned int GetOptimalBlockSize() const; +#endif + + FixedSizeSecBlock m_key; + FixedSizeAlignedSecBlock m_state; +}; + +/// \brief Sosemanuk stream cipher +/// \details is a stream cipher developed by Come Berbain, Olivier Billet, Anne Canteaut, Nicolas Courtois, +/// Henri Gilbert, Louis Goubin, Aline Gouget, Louis Granboulan, Cédric Lauradoux, Marine Minier, Thomas +/// Pornin and Hervé Sibert. Sosemanuk is one of the final four Profile 1 (software) ciphers selected for +/// the eSTREAM Portfolio. +/// \sa Sosemanuk +/// \since Crypto++ 5.5 +struct Sosemanuk : public SosemanukInfo, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, SosemanukInfo> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/speck.h b/third_party/cryptoppwin/include/cryptopp/speck.h new file mode 100644 index 00000000..5ab3ece7 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/speck.h @@ -0,0 +1,206 @@ +// speck.h - written and placed in the public domain by Jeffrey Walton + +/// \file speck.h +/// \brief Classes for the Speck block cipher +/// \details Speck is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith, +/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers. +/// \sa The SIMON and SPECK Families of +/// Lightweight Block Ciphers, +/// The Simon and Speck GitHub and +/// SPECK on the Crypto++ wiki. +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_SPECK_H +#define CRYPTOPP_SPECK_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 || \ + CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8 || \ + CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64 +# ifndef CRYPTOPP_DISABLE_SPECK_SIMD +# define CRYPTOPP_SPECK128_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_SPECK128_ADVANCED_PROCESS_BLOCKS +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief SPECK block cipher information +/// \tparam L block size of the cipher, in bytes +/// \tparam D default key length, in bytes +/// \tparam N minimum key length, in bytes +/// \tparam M maximum key length, in bytes +/// \since Crypto++ 6.0 +template +struct SPECK_Info : public FixedBlockSize, VariableKeyLength +{ + /// \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(Keylength) + return "SPECK-" + IntToString(L*8); + } +}; + +/// \brief SPECK block cipher base class +/// \tparam W the word type +/// \details User code should use SPECK64 or SPECK128 +/// \sa SPECK64, SPECK128, SPECK +/// \since Crypto++ 6.0 +template +struct SPECK_Base +{ + virtual ~SPECK_Base() {} + SPECK_Base() : m_kwords(0), m_rounds(0) {} + + typedef SecBlock > AlignedSecBlock; + mutable AlignedSecBlock m_wspace; // workspace + AlignedSecBlock m_rkeys; // round keys + unsigned int m_kwords; // number of key words + unsigned int m_rounds; // number of rounds +}; + +/// \brief SPECK 64-bit block cipher +/// \details Speck is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith, +/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers. +/// \details SPECK64 provides 64-bit block size. The valid key sizes are 96-bit and 128-bit. +/// \sa SPECK64, SPECK128, The SIMON and SPECK +/// Families of Lightweight Block Ciphers, +/// The Simon and Speck GitHub, SPECK on the +/// Crypto++ wiki +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE SPECK64 : public SPECK_Info<8, 12, 12, 16>, public BlockCipherDocumentation +{ +public: + /// \brief SPECK64 block cipher base implementation + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base, public BlockCipherImpl > + { + public: + /// \brief The algorithm name + /// \return the algorithm name + /// \details AlgorithmName returns the algorithm's name as a + /// member function. + std::string AlgorithmName() const { + return StaticAlgorithmName() + (m_kwords == 0 ? "" : + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")"); + } + + std::string AlgorithmProvider() const; + + /// \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; + + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief SPECK64 encryption transformation + /// \details Enc provides the encryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief SPECK64 decryption transformation + /// \details Dec provides the decryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief SPECK 128-bit block cipher +/// \details Speck is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith, +/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers. +/// \details SPECK128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit. +/// \sa SPECK64, SPECK128, The SIMON and SPECK +/// Families of Lightweight Block Ciphers, +/// The Simon and Speck GitHub, SPECK on the +/// Crypto++ wiki +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE SPECK128 : public SPECK_Info<16, 16, 16, 32>, public BlockCipherDocumentation +{ +public: + /// \brief SPECK128 block cipher base implementation + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base, public BlockCipherImpl > + { + public: + /// \brief The algorithm name + /// \return the algorithm name + /// \details AlgorithmName returns the algorithm's name as a + /// member function. + std::string AlgorithmName() const { + return StaticAlgorithmName() + (m_kwords == 0 ? "" : + "(" + IntToString(m_kwords*sizeof(word64)*8) + ")"); + } + + std::string AlgorithmProvider() const; + + /// \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; + + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief SPECK128 encryption transformation + /// \details Enc provides the encryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + + /// \brief SPECK128 decryption transformation + /// \details Dec provides the decryption transformation. + /// All key sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +NAMESPACE_END + +#endif // CRYPTOPP_SPECK_H diff --git a/third_party/cryptoppwin/include/cryptopp/square.h b/third_party/cryptoppwin/include/cryptopp/square.h new file mode 100644 index 00000000..e43e796d --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/square.h @@ -0,0 +1,63 @@ +// square.h - originally written and placed in the public domain by Wei Dai + +/// \file square.h +/// \brief Classes for the Square block cipher + +#ifndef CRYPTOPP_SQUARE_H +#define CRYPTOPP_SQUARE_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Square block cipher information +/// \since Crypto++ 2.2 +struct Square_Info : public FixedBlockSize<16>, public FixedKeyLength<16>, FixedRounds<8> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Square";} +}; + +/// \brief Square block cipher +/// \sa Square +/// \since Crypto++ 2.2 +class Square : public Square_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock m_roundkeys; + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + private: + static const byte Se[256]; + static const word32 Te[4][256]; + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + private: + static const byte Sd[256]; + static const word32 Td[4][256]; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Square::Encryption SquareEncryption; +typedef Square::Decryption SquareDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/stdcpp.h b/third_party/cryptoppwin/include/cryptopp/stdcpp.h new file mode 100644 index 00000000..4b5d8426 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/stdcpp.h @@ -0,0 +1,101 @@ +// stdcpp.h - originally written and placed in the public domain by Wei Dai + +/// \file stdcpp.h +/// \brief Common C++ header files + +#ifndef CRYPTOPP_STDCPP_H +#define CRYPTOPP_STDCPP_H + +#if (CRYPTOPP_MSC_VERSION >= 1500) +#define _DO_NOT_DECLARE_INTERLOCKED_INTRINSICS_IN_MEMORY +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// http://connect.microsoft.com/VisualStudio/feedback/details/1600701/type-info-does-not-compile-with-has-exceptions-0 +#if defined(CRYPTOPP_MSC_VERSION) && (CRYPTOPP_MSC_VERSION < 1900) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 0) +namespace std { + using ::type_info; +} +#endif + +// workaround needed for IBM XLC and debug heaps on AIX +#if defined(_AIX) && (defined(__xlc__) || defined(__xlC__) || defined(__ibmxl__)) +# if defined(__DEBUG_ALLOC__) +namespace std { + using ::_debug_memset; + using ::_debug_memcpy; +} +# endif +#endif + +// make_unchecked_array_iterator +#if (CRYPTOPP_MSC_VERSION >= 1600) +#include +#endif + +#if defined(CRYPTOPP_CXX11_ATOMIC) +#include +#endif + +#if defined(CRYPTOPP_CXX11_SYNCHRONIZATION) +#include +#endif + +#if defined(CRYPTOPP_CXX11_RVALUES) +# include +#endif + +#include +#include +#include +#include + +// It is 2019 and VS2017/Win10 still can't compile a +// program that includes without making users +// do something special. "Epic fail" comes to mind. +// Also see https://github.com/weidai11/cryptopp/issues/781 +#ifndef CRYPTOPP_MSC_VERSION +# include +#endif + +// uintptr_t and ptrdiff_t +#if defined(__SUNPRO_CC) +# if (__SUNPRO_CC >= 0x5100) +# include +# endif +#elif defined(CRYPTOPP_MSC_VERSION) +# if (CRYPTOPP_MSC_VERSION >= 1700) +# include +# else +# include +# endif +#elif (__cplusplus < 201103L) +# include +#endif + +// workaround needed on Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21 +#ifdef CRYPTOPP_INCLUDE_VECTOR_CC +# include +#endif + +// C++Builder's standard library (Dinkumware) do not have C's global log() function +// https://github.com/weidai11/cryptopp/issues/520 +#ifdef __BORLANDC__ +using std::log; +#endif + +#endif // CRYPTOPP_STDCPP_H diff --git a/third_party/cryptoppwin/include/cryptopp/strciphr.h b/third_party/cryptoppwin/include/cryptopp/strciphr.h new file mode 100644 index 00000000..ef8989db --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/strciphr.h @@ -0,0 +1,737 @@ +// strciphr.h - originally written and placed in the public domain by Wei Dai + +/// \file strciphr.h +/// \brief Classes for implementing stream ciphers +/// \details This file contains helper classes for implementing stream ciphers. +/// All this infrastructure may look very complex compared to what's in Crypto++ 4.x, +/// but stream ciphers implementations now support a lot of new functionality, +/// including better performance (minimizing copying), resetting of keys and IVs, and +/// methods to query which features are supported by a cipher. +/// \details Here's an explanation of these classes. The word "policy" is used here to +/// mean a class with a set of methods that must be implemented by individual stream +/// cipher implementations. This is usually much simpler than the full stream cipher +/// API, which is implemented by either AdditiveCipherTemplate or CFB_CipherTemplate +/// using the policy. So for example, an implementation of SEAL only needs to implement +/// the AdditiveCipherAbstractPolicy interface (since it's an additive cipher, i.e., it +/// xors a keystream into the plaintext). See this line in seal.h: +///
+///     typedef SymmetricCipherFinal\, AdditiveCipherTemplate\<\> \> \> Encryption;
+/// 
+/// \details AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't +/// need to take a policy class as a template parameter (although this is allowed), so +/// that their code is not duplicated for each new cipher. Instead they each get a +/// reference to an abstract policy interface by calling AccessPolicy() on itself, so +/// AccessPolicy() must be overridden to return the actual policy reference. This is done +/// by the ConcretePolicyHolder class. Finally, SymmetricCipherFinal implements the +/// constructors and other functions that must be implemented by the most derived class. + +#ifndef CRYPTOPP_STRCIPHR_H +#define CRYPTOPP_STRCIPHR_H + +#include "config.h" + +#if CRYPTOPP_MSC_VERSION +# pragma warning(push) +# pragma warning(disable: 4127 4189 4231 4275) +#endif + +#include "cryptlib.h" +#include "seckey.h" +#include "secblock.h" +#include "argnames.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Access a stream cipher policy object +/// \tparam POLICY_INTERFACE class implementing AbstractPolicyHolder +/// \tparam BASE class or type to use as a base class +template +class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE +{ +public: + typedef POLICY_INTERFACE PolicyInterface; + virtual ~AbstractPolicyHolder() {} + +protected: + virtual const POLICY_INTERFACE & GetPolicy() const =0; + virtual POLICY_INTERFACE & AccessPolicy() =0; +}; + +/// \brief Stream cipher policy object +/// \tparam POLICY class implementing AbstractPolicyHolder +/// \tparam BASE class or type to use as a base class +template +class ConcretePolicyHolder : public BASE, protected POLICY +{ +public: + virtual ~ConcretePolicyHolder() {} +protected: + const POLICY_INTERFACE & GetPolicy() const {return *this;} + POLICY_INTERFACE & AccessPolicy() {return *this;} +}; + +/// \brief Keystream operation flags +/// \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize() +/// and AdditiveCipherAbstractPolicy::GetAlignment() +enum KeystreamOperationFlags { + /// \brief Output buffer is aligned + OUTPUT_ALIGNED=1, + /// \brief Input buffer is aligned + INPUT_ALIGNED=2, + /// \brief Input buffer is NULL + INPUT_NULL = 4 +}; + +/// \brief Keystream operation flags +/// \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize() +/// and AdditiveCipherAbstractPolicy::GetAlignment() +enum KeystreamOperation { + /// \brief Write the keystream to the output buffer, input is NULL + WRITE_KEYSTREAM = INPUT_NULL, + /// \brief Write the keystream to the aligned output buffer, input is NULL + WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED, + /// \brief XOR the input buffer and keystream, write to the output buffer + XOR_KEYSTREAM = 0, + /// \brief XOR the aligned input buffer and keystream, write to the output buffer + XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED, + /// \brief XOR the input buffer and keystream, write to the aligned output buffer + XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED, + /// \brief XOR the aligned input buffer and keystream, write to the aligned output buffer + XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED +}; + +/// \brief Policy object for additive stream ciphers +struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy +{ + virtual ~AdditiveCipherAbstractPolicy() {} + + /// \brief Provides data alignment requirements + /// \return data alignment requirements, in bytes + /// \details Internally, the default implementation returns 1. If the stream cipher is implemented + /// using an SSE2 ASM or intrinsics, then the value returned is usually 16. + virtual unsigned int GetAlignment() const {return 1;} + + /// \brief Provides number of bytes operated upon during an iteration + /// \return bytes operated upon during an iteration, in bytes + /// \sa GetOptimalBlockSize() + virtual unsigned int GetBytesPerIteration() const =0; + + /// \brief Provides number of ideal bytes to process + /// \return the ideal number of bytes to process + /// \details Internally, the default implementation returns GetBytesPerIteration() + /// \sa GetBytesPerIteration() + virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();} + + /// \brief Provides buffer size based on iterations + /// \return the buffer size based on iterations, in bytes + virtual unsigned int GetIterationsToBuffer() const =0; + + /// \brief Generate the keystream + /// \param keystream the key stream + /// \param iterationCount the number of iterations to generate the key stream + /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() + virtual void WriteKeystream(byte *keystream, size_t iterationCount) + {OperateKeystream(KeystreamOperation(INPUT_NULL | static_cast(IsAlignedOn(keystream, GetAlignment()))), keystream, NULLPTR, iterationCount);} + + /// \brief Flag indicating + /// \return true if the stream can be generated independent of the transformation input, false otherwise + /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() + virtual bool CanOperateKeystream() const {return false;} + + /// \brief Operates the keystream + /// \param operation the operation with additional flags + /// \param output the output buffer + /// \param input the input buffer + /// \param iterationCount the number of iterations to perform on the input + /// \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer, + /// which will be derived from GetBytesPerIteration(). + /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation() + virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) + {CRYPTOPP_UNUSED(operation); CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); + CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false);} + + /// \brief Key the cipher + /// \param params set of NameValuePairs use to initialize this object + /// \param key a byte array used to key the cipher + /// \param length the size of the key array + virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; + + /// \brief Resynchronize the cipher + /// \param keystreamBuffer the keystream buffer + /// \param iv a byte array used to resynchronize the cipher + /// \param length the size of the IV array + virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) + {CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); + throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} + + /// \brief Flag indicating random access + /// \return true if the cipher is seekable, false otherwise + /// \sa SeekToIteration() + virtual bool CipherIsRandomAccess() const =0; + + /// \brief Seeks to a random position in the stream + /// \sa CipherIsRandomAccess() + virtual void SeekToIteration(lword iterationCount) + {CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(!CipherIsRandomAccess()); + throw NotImplemented("StreamTransformation: this object doesn't support random access");} + + /// \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). + /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". + /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics + /// instead of ASM. + /// \details Algorithms which combine different instructions or ISAs provide the + /// dominant one. For example on x86 AES/GCM returns "AESNI" rather than + /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". + /// \note Provider is not universally implemented yet. + virtual std::string AlgorithmProvider() const { return "C++"; } +}; + +/// \brief Base class for additive stream ciphers +/// \tparam WT word type +/// \tparam W count of words +/// \tparam X bytes per iteration count +/// \tparam BASE AdditiveCipherAbstractPolicy derived base class +template +struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE +{ + /// \brief Word type for the cipher + typedef WT WordType; + + /// \brief Number of bytes for an iteration + /// \details BYTES_PER_ITERATION is the product sizeof(WordType) * W. + /// For example, ChaCha uses 16 each word32, and the value of + /// BYTES_PER_ITERATION is 64. Each invocation of the ChaCha block function + /// produces 64 bytes of keystream. + CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W); + + virtual ~AdditiveCipherConcretePolicy() {} + + /// \brief Provides data alignment requirements + /// \return data alignment requirements, in bytes + /// \details Internally, the default implementation returns 1. If the stream + /// cipher is implemented using an SSE2 ASM or intrinsics, then the value + /// returned is usually 16. + unsigned int GetAlignment() const {return GetAlignmentOf();} + + /// \brief Provides number of bytes operated upon during an iteration + /// \return bytes operated upon during an iteration, in bytes + /// \sa GetOptimalBlockSize() + unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;} + + /// \brief Provides buffer size based on iterations + /// \return the buffer size based on iterations, in bytes + unsigned int GetIterationsToBuffer() const {return X;} + + /// \brief Flag indicating + /// \return true if the stream can be generated independent of the + /// transformation input, false otherwise + /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() + bool CanOperateKeystream() const {return true;} + + /// \brief Operates the keystream + /// \param operation the operation with additional flags + /// \param output the output buffer + /// \param input the input buffer + /// \param iterationCount the number of iterations to perform on the input + /// \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer, + /// which will be derived from GetBytesPerIteration(). + /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation() + virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0; +}; + +/// \brief Helper macro to implement OperateKeystream +/// \param x KeystreamOperation mask +/// \param b Endian order +/// \param i index in output buffer +/// \param a value to output +#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \ + PutWord(((x & OUTPUT_ALIGNED) != 0), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? (a) : (a) ^ GetWord(((x & INPUT_ALIGNED) != 0), b, input+i*sizeof(WordType))); + +/// \brief Helper macro to implement OperateKeystream +/// \param x KeystreamOperation mask +/// \param i index in output buffer +/// \param a value to output +#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\ + __m128i t = (x & INPUT_NULL) ? a : _mm_xor_si128(a, (x & INPUT_ALIGNED) ? _mm_load_si128((__m128i *)input+i) : _mm_loadu_si128((__m128i *)input+i));\ + if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\ + else _mm_storeu_si128((__m128i *)output+i, t);} + +/// \brief Helper macro to implement OperateKeystream +#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \ + switch (operation) \ + { \ + case WRITE_KEYSTREAM: \ + x(EnumToInt(WRITE_KEYSTREAM)) \ + break; \ + case XOR_KEYSTREAM: \ + x(EnumToInt(XOR_KEYSTREAM)) \ + input += y; \ + break; \ + case XOR_KEYSTREAM_INPUT_ALIGNED: \ + x(EnumToInt(XOR_KEYSTREAM_INPUT_ALIGNED)) \ + input += y; \ + break; \ + case XOR_KEYSTREAM_OUTPUT_ALIGNED: \ + x(EnumToInt(XOR_KEYSTREAM_OUTPUT_ALIGNED)) \ + input += y; \ + break; \ + case WRITE_KEYSTREAM_ALIGNED: \ + x(EnumToInt(WRITE_KEYSTREAM_ALIGNED)) \ + break; \ + case XOR_KEYSTREAM_BOTH_ALIGNED: \ + x(EnumToInt(XOR_KEYSTREAM_BOTH_ALIGNED)) \ + input += y; \ + break; \ + } \ + output += y; + +/// \brief Base class for additive stream ciphers with SymmetricCipher interface +/// \tparam BASE AbstractPolicyHolder base class +template > +class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator +{ +public: + virtual ~AdditiveCipherTemplate() {} + AdditiveCipherTemplate() : m_leftOver(0) {} + + /// \brief Generate random array of bytes + /// \param output the byte buffer + /// \param size the length of the buffer, in bytes + /// \details All generated values are uniformly distributed over the range specified + /// within the constraints of a particular generator. + void GenerateBlock(byte *output, size_t size); + + /// \brief Apply keystream to data + /// \param outString a buffer to write the transformed data + /// \param inString a buffer to read the data + /// \param length the size of the buffers, in bytes + /// \details This is the primary method to operate a stream cipher. For example: + ///
+	///     size_t size = 30;
+	///     byte plain[size] = "Do or do not; there is no try";
+	///     byte cipher[size];
+	///     ...
+	///     ChaCha20 chacha(key, keySize);
+	///     chacha.ProcessData(cipher, plain, size);
+	/// 
+ /// \details You should use distinct buffers for inString and outString. If the buffers + /// are the same, then the data will be copied to an internal buffer to avoid GCC alias + /// violations. The internal copy will impact performance. + /// \sa Issue 1088, 36% loss + /// of performance with AES, Issue + /// 1010, HIGHT cipher troubles with FileSource + void ProcessData(byte *outString, const byte *inString, size_t length); + + /// \brief Resynchronize the cipher + /// \param iv a byte array used to resynchronize the cipher + /// \param length the size of the IV array + void Resynchronize(const byte *iv, int length=-1); + + /// \brief Provides number of ideal bytes to process + /// \return the ideal number of bytes to process + /// \details Internally, the default implementation returns GetBytesPerIteration() + /// \sa GetBytesPerIteration() and GetOptimalNextBlockSize() + unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();} + + /// \brief Provides number of ideal bytes to process + /// \return the ideal number of bytes to process + /// \details Internally, the default implementation returns remaining unprocessed bytes + /// \sa GetBytesPerIteration() and OptimalBlockSize() + unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;} + + /// \brief Provides number of ideal data alignment + /// \return the ideal data alignment, in bytes + /// \sa GetAlignment() and OptimalBlockSize() + unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} + + /// \brief Determines if the cipher is self inverting + /// \return true if the stream cipher is self inverting, false otherwise + bool IsSelfInverting() const {return true;} + + /// \brief Determines if the cipher is a forward transformation + /// \return true if the stream cipher is a forward transformation, false otherwise + bool IsForwardTransformation() const {return true;} + + /// \brief Flag indicating random access + /// \return true if the cipher is seekable, false otherwise + /// \sa Seek() + bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();} + + /// \brief Seeks to a random position in the stream + /// \param position the absolute position in the stream + /// \sa IsRandomAccess() + void Seek(lword position); + + /// \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). + /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". + /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics + /// instead of ASM. + /// \details Algorithms which combine different instructions or ISAs provide the + /// dominant one. For example on x86 AES/GCM returns "AESNI" rather than + /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". + /// \note Provider is not universally implemented yet. + std::string AlgorithmProvider() const { return this->GetPolicy().AlgorithmProvider(); } + + typedef typename BASE::PolicyInterface PolicyInterface; + +protected: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + + unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} + + inline byte * KeystreamBufferBegin() {return this->m_buffer.data();} + inline byte * KeystreamBufferEnd() {return (PtrAdd(this->m_buffer.data(), this->m_buffer.size()));} + + AlignedSecByteBlock m_buffer; + size_t m_leftOver; +}; + +/// \brief Policy object for feedback based stream ciphers +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy +{ +public: + virtual ~CFB_CipherAbstractPolicy() {} + + /// \brief Provides data alignment requirements + /// \return data alignment requirements, in bytes + /// \details Internally, the default implementation returns 1. If the stream cipher is implemented + /// using an SSE2 ASM or intrinsics, then the value returned is usually 16. + virtual unsigned int GetAlignment() const =0; + + /// \brief Provides number of bytes operated upon during an iteration + /// \return bytes operated upon during an iteration, in bytes + /// \sa GetOptimalBlockSize() + virtual unsigned int GetBytesPerIteration() const =0; + + /// \brief Access the feedback register + /// \return pointer to the first byte of the feedback register + virtual byte * GetRegisterBegin() =0; + + /// \brief TODO + virtual void TransformRegister() =0; + + /// \brief Flag indicating iteration support + /// \return true if the cipher supports iteration, false otherwise + virtual bool CanIterate() const {return false;} + + /// \brief Iterate the cipher + /// \param output the output buffer + /// \param input the input buffer + /// \param dir the direction of the cipher + /// \param iterationCount the number of iterations to perform on the input + /// \sa IsSelfInverting() and IsForwardTransformation() + virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) + {CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(dir); + CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false); + throw Exception(Exception::OTHER_ERROR, "SimpleKeyingInterface: unexpected error");} + + /// \brief Key the cipher + /// \param params set of NameValuePairs use to initialize this object + /// \param key a byte array used to key the cipher + /// \param length the size of the key array + virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; + + /// \brief Resynchronize the cipher + /// \param iv a byte array used to resynchronize the cipher + /// \param length the size of the IV array + virtual void CipherResynchronize(const byte *iv, size_t length) + {CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); + throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} + + /// \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). + /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". + /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics + /// instead of ASM. + /// \details Algorithms which combine different instructions or ISAs provide the + /// dominant one. For example on x86 AES/GCM returns "AESNI" rather than + /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". + /// \note Provider is not universally implemented yet. + virtual std::string AlgorithmProvider() const { return "C++"; } +}; + +/// \brief Base class for feedback based stream ciphers +/// \tparam WT word type +/// \tparam W count of words +/// \tparam BASE CFB_CipherAbstractPolicy derived base class +template +struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE +{ + typedef WT WordType; + + virtual ~CFB_CipherConcretePolicy() {} + + /// \brief Provides data alignment requirements + /// \return data alignment requirements, in bytes + /// \details Internally, the default implementation returns 1. If the stream cipher is implemented + /// using an SSE2 ASM or intrinsics, then the value returned is usually 16. + unsigned int GetAlignment() const {return sizeof(WordType);} + + /// \brief Provides number of bytes operated upon during an iteration + /// \return bytes operated upon during an iteration, in bytes + /// \sa GetOptimalBlockSize() + unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} + + /// \brief Flag indicating iteration support + /// \return true if the cipher supports iteration, false otherwise + bool CanIterate() const {return true;} + + /// \brief Perform one iteration in the forward direction + void TransformRegister() {this->Iterate(NULLPTR, NULLPTR, ENCRYPTION, 1);} + + /// \brief Provides alternate access to a feedback register + /// \tparam B enumeration indicating endianness + /// \details RegisterOutput() provides alternate access to the feedback register. The + /// enumeration B is BigEndian or LittleEndian. Repeatedly applying operator() + /// results in advancing in the register. + template + struct RegisterOutput + { + RegisterOutput(byte *output, const byte *input, CipherDir dir) + : m_output(output), m_input(input), m_dir(dir) {} + + /// \brief XOR feedback register with data + /// \param registerWord data represented as a word type + /// \return reference to the next feedback register word + inline RegisterOutput& operator()(WordType ®isterWord) + { + //CRYPTOPP_ASSERT(IsAligned(m_output)); + //CRYPTOPP_ASSERT(IsAligned(m_input)); + + if (!NativeByteOrderIs(B::ToEnum())) + registerWord = ByteReverse(registerWord); + + if (m_dir == ENCRYPTION) + { + if (m_input == NULLPTR) + { + CRYPTOPP_ASSERT(m_output == NULLPTR); + } + else + { + // WordType ct = *(const WordType *)m_input ^ registerWord; + WordType ct = GetWord(false, NativeByteOrder::ToEnum(), m_input) ^ registerWord; + registerWord = ct; + + // *(WordType*)m_output = ct; + PutWord(false, NativeByteOrder::ToEnum(), m_output, ct); + + m_input += sizeof(WordType); + m_output += sizeof(WordType); + } + } + else + { + // WordType ct = *(const WordType *)m_input; + WordType ct = GetWord(false, NativeByteOrder::ToEnum(), m_input); + + // *(WordType*)m_output = registerWord ^ ct; + PutWord(false, NativeByteOrder::ToEnum(), m_output, registerWord ^ ct); + registerWord = ct; + + m_input += sizeof(WordType); + m_output += sizeof(WordType); + } + + // registerWord is left unreversed so it can be xor-ed with further input + + return *this; + } + + byte *m_output; + const byte *m_input; + CipherDir m_dir; + }; +}; + +/// \brief Base class for feedback based stream ciphers with SymmetricCipher interface +/// \tparam BASE AbstractPolicyHolder base class +template +class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE +{ +public: + virtual ~CFB_CipherTemplate() {} + CFB_CipherTemplate() : m_leftOver(0) {} + + /// \brief Apply keystream to data + /// \param outString a buffer to write the transformed data + /// \param inString a buffer to read the data + /// \param length the size of the buffers, in bytes + /// \details This is the primary method to operate a stream cipher. For example: + ///
+	///     size_t size = 30;
+	///     byte plain[size] = "Do or do not; there is no try";
+	///     byte cipher[size];
+	///     ...
+	///     ChaCha20 chacha(key, keySize);
+	///     chacha.ProcessData(cipher, plain, size);
+	/// 
+ /// \details You should use distinct buffers for inString and outString. If the buffers + /// are the same, then the data will be copied to an internal buffer to avoid GCC alias + /// violations. The internal copy will impact performance. + /// \sa Issue 1088, 36% loss + /// of performance with AES, Issue + /// 1010, HIGHT cipher troubles with FileSource + void ProcessData(byte *outString, const byte *inString, size_t length); + + /// \brief Resynchronize the cipher + /// \param iv a byte array used to resynchronize the cipher + /// \param length the size of the IV array + void Resynchronize(const byte *iv, int length=-1); + + /// \brief Provides number of ideal bytes to process + /// \return the ideal number of bytes to process + /// \details Internally, the default implementation returns GetBytesPerIteration() + /// \sa GetBytesPerIteration() and GetOptimalNextBlockSize() + unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} + + /// \brief Provides number of ideal bytes to process + /// \return the ideal number of bytes to process + /// \details Internally, the default implementation returns remaining unprocessed bytes + /// \sa GetBytesPerIteration() and OptimalBlockSize() + unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;} + + /// \brief Provides number of ideal data alignment + /// \return the ideal data alignment, in bytes + /// \sa GetAlignment() and OptimalBlockSize() + unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} + + /// \brief Flag indicating random access + /// \return true if the cipher is seekable, false otherwise + /// \sa Seek() + bool IsRandomAccess() const {return false;} + + /// \brief Determines if the cipher is self inverting + /// \return true if the stream cipher is self inverting, false otherwise + bool IsSelfInverting() const {return false;} + + /// \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). + /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". + /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics + /// instead of ASM. + /// \details Algorithms which combine different instructions or ISAs provide the + /// dominant one. For example on x86 AES/GCM returns "AESNI" rather than + /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". + /// \note Provider is not universally implemented yet. + std::string AlgorithmProvider() const { return this->GetPolicy().AlgorithmProvider(); } + + typedef typename BASE::PolicyInterface PolicyInterface; + +protected: + virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0; + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + + size_t m_leftOver; +}; + +/// \brief Base class for feedback based stream ciphers in the forward direction with SymmetricCipher interface +/// \tparam BASE AbstractPolicyHolder base class +template > +class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return true;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); +}; + +/// \brief Base class for feedback based stream ciphers in the reverse direction with SymmetricCipher interface +/// \tparam BASE AbstractPolicyHolder base class +template > +class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return false;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); +}; + +/// \brief Base class for feedback based stream ciphers with a mandatory block size +/// \tparam BASE CFB_EncryptionTemplate or CFB_DecryptionTemplate base class +template +class CFB_RequireFullDataBlocks : public BASE +{ +public: + unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} +}; + +/// \brief SymmetricCipher implementation +/// \tparam BASE AbstractPolicyHolder derived base class +/// \tparam INFO AbstractPolicyHolder derived information class +/// \sa Weak::ARC4, ChaCha8, ChaCha12, ChaCha20, Salsa20, SEAL, Sosemanuk, WAKE +template +class SymmetricCipherFinal : public AlgorithmImpl, INFO> +{ +public: + virtual ~SymmetricCipherFinal() {} + + /// \brief Construct a stream cipher + SymmetricCipherFinal() {} + + /// \brief Construct a stream cipher + /// \param key a byte array used to key the cipher + /// \details This overload uses DEFAULT_KEYLENGTH + SymmetricCipherFinal(const byte *key) + {this->SetKey(key, this->DEFAULT_KEYLENGTH);} + + /// \brief Construct a stream cipher + /// \param key a byte array used to key the cipher + /// \param length the size of the key array + SymmetricCipherFinal(const byte *key, size_t length) + {this->SetKey(key, length);} + + /// \brief Construct a stream cipher + /// \param key a byte array used to key the cipher + /// \param length the size of the key array + /// \param iv a byte array used as an initialization vector + SymmetricCipherFinal(const byte *key, size_t length, const byte *iv) + {this->SetKeyWithIV(key, length, iv);} + + /// \brief Clone a SymmetricCipher + /// \return a new SymmetricCipher based on this object + Clonable * Clone() const {return static_cast(new SymmetricCipherFinal(*this));} +}; + +NAMESPACE_END + +// Used by dll.cpp to ensure objects are in dll.o, and not strciphr.o. +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +# include "strciphr.cpp" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder; +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; + +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; + +NAMESPACE_END + +#if CRYPTOPP_MSC_VERSION +# pragma warning(pop) +#endif + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/tea.h b/third_party/cryptoppwin/include/cryptopp/tea.h new file mode 100644 index 00000000..e4ba5df3 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/tea.h @@ -0,0 +1,161 @@ +// tea.h - originally written and placed in the public domain by Wei Dai + +/// \file tea.h +/// \brief Classes for the TEA, BTEA and XTEA block ciphers + +#ifndef CRYPTOPP_TEA_H +#define CRYPTOPP_TEA_H + +#include "seckey.h" +#include "secblock.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief TEA block cipher information +struct TEA_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public VariableRounds<32> +{ + /// \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 "TEA";} +}; + +/// \brief TEA block cipher +/// \sa TEA +class TEA : public TEA_Info, public BlockCipherDocumentation +{ + /// \brief TEA block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock m_k; + word32 m_limit; + }; + + /// \brief TEA block cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief TEA block cipher decryption operation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef TEA::Encryption TEAEncryption; +typedef TEA::Decryption TEADecryption; + +/// \brief XTEA block cipher information +struct XTEA_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public VariableRounds<32> +{ + /// \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 "XTEA";} +}; + +/// \brief XTEA block cipher +/// \sa XTEA +class XTEA : public XTEA_Info, public BlockCipherDocumentation +{ + /// \brief XTEA block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock m_k; + word32 m_limit; + }; + + /// \brief XTEA block cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief XTEA block cipher decryption operation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +/// \brief BTEA block cipher information +struct BTEA_Info : public FixedKeyLength<16> +{ + /// \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 "BTEA";} +}; + +/// \brief BTEA block cipher +/// \details Corrected Block TEA as described in "xxtea". This class hasn't been tested yet. +/// \sa Correction to xtea and +/// Corrected Block TEA. +class BTEA : public BTEA_Info, public BlockCipherDocumentation +{ + /// \brief BTEA block cipher default operation + class CRYPTOPP_NO_VTABLE Base : public AlgorithmImpl, BTEA_Info> + { + public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) + { + CRYPTOPP_UNUSED(length), CRYPTOPP_UNUSED(params); + m_blockSize = params.GetIntValueWithDefault("BlockSize", 60*4); + GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, key, KEYLENGTH); + } + + unsigned int BlockSize() const {return m_blockSize;} + + protected: + FixedSizeSecBlock m_k; + unsigned int m_blockSize; + }; + + /// \brief BTEA block cipher encryption operation + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief BTEA block cipher decryption operation + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/threefish.h b/third_party/cryptoppwin/include/cryptopp/threefish.h new file mode 100644 index 00000000..ab32ce01 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/threefish.h @@ -0,0 +1,201 @@ +// threefish.h - written and placed in the public domain by Jeffrey Walton +// Based on public domain code by Keru Kuro. Kuro's code is +// available at http://cppcrypto.sourceforge.net/. + +/// \file Threefish.h +/// \brief Classes for the Threefish block cipher +/// \since Crypto++ 6.0 + +#ifndef CRYPTOPP_THREEFISH_H +#define CRYPTOPP_THREEFISH_H + +#include "config.h" +#include "seckey.h" +#include "secblock.h" +#include "algparam.h" +#include "argnames.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Threefish block cipher information +/// \tparam BS block size of the cipher, in bytes +/// \since Crypto++ 6.0 +template +struct Threefish_Info : public FixedBlockSize, FixedKeyLength +{ + static const std::string StaticAlgorithmName() + { + // Format is Cipher-Blocksize(Keylength) + return "Threefish-" + IntToString(BS*8) + "(" + IntToString(BS*8) + ")"; + } +}; + +/// \brief Threefish block cipher base class +/// \tparam BS block size of the cipher, in bytes +/// \details User code should use Threefish256, Threefish512, Threefish1024 +/// \sa Threefish256, Threefish512, Threefish1024, Threefish +/// \since Crypto++ 6.0 +template +struct CRYPTOPP_NO_VTABLE Threefish_Base +{ + virtual ~Threefish_Base() {} + + void SetTweak(const NameValuePairs ¶ms) + { + m_tweak.New(3); + ConstByteArrayParameter t; + if (params.GetValue(Name::Tweak(), t)) + { + // Tweak size is fixed at 16 for Threefish + CRYPTOPP_ASSERT(t.size() == 16); + GetUserKey(LITTLE_ENDIAN_ORDER, m_tweak.begin(), 2, t.begin(), 16); + m_tweak[2] = m_tweak[0] ^ m_tweak[1]; + } + else + { + std::memset(m_tweak.begin(), 0x00, 24); + } + } + + typedef SecBlock > AlignedSecBlock64; + mutable AlignedSecBlock64 m_wspace; // workspace + AlignedSecBlock64 m_rkey; // keys + AlignedSecBlock64 m_tweak; +}; + +/// \brief Threefish 256-bit block cipher +/// \details Threefish256 provides 256-bit block size. The valid key size is 256-bit. +/// \note Crypto++ provides a byte oriented implementation +/// \sa Threefish512, Threefish1024, Threefish +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE Threefish256 : public Threefish_Info<32>, public BlockCipherDocumentation +{ +public: + /// \brief Threefish block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : public Threefish_Base<32>, public BlockCipherImpl > + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief Encryption transformation + /// \details Enc provides implementation for encryption transformation. All key and block + /// sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + protected: + 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++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + protected: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Threefish256::Encryption Threefish256Encryption; +typedef Threefish256::Decryption Threefish256Decryption; + +/// \brief Threefish 512-bit block cipher +/// \details Threefish512 provides 512-bit block size. The valid key size is 512-bit. +/// \note Crypto++ provides a byte oriented implementation +/// \sa Threefish256, Threefish1024, Threefish +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE Threefish512 : public Threefish_Info<64>, public BlockCipherDocumentation +{ +public: + /// \brief Threefish block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : public Threefish_Base<64>, public BlockCipherImpl > + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief Encryption transformation + /// \details Enc provides implementation for encryption transformation. All key and block + /// sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + protected: + 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++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + protected: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Threefish512::Encryption Threefish512Encryption; +typedef Threefish512::Decryption Threefish512Decryption; + +/// \brief Threefish 1024-bit block cipher +/// \details Threefish1024 provides 1024-bit block size. The valid key size is 1024-bit. +/// \note Crypto++ provides a byte oriented implementation +/// \sa Threefish256, Threefish512, Threefish +/// \since Crypto++ 6.0 +class CRYPTOPP_NO_VTABLE Threefish1024 : public Threefish_Info<128>, public BlockCipherDocumentation +{ +public: + /// \brief Threefish block cipher transformation functions + /// \details Provides implementation common to encryption and decryption + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Base : public Threefish_Base<128>, public BlockCipherImpl > + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + }; + + /// \brief Encryption transformation + /// \details Enc provides implementation for encryption transformation. All key and block + /// sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Enc : public Base + { + protected: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + /// \brief Encryption transformation + /// \details Dec provides implementation for decryption transformation. All key and block + /// sizes are supported. + /// \since Crypto++ 6.0 + class CRYPTOPP_NO_VTABLE Dec : public Base + { + protected: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Threefish1024::Encryption Threefish1024Encryption; +typedef Threefish1024::Decryption Threefish1024Decryption; + +NAMESPACE_END + +#endif // CRYPTOPP_THREEFISH_H diff --git a/third_party/cryptoppwin/include/cryptopp/tiger.h b/third_party/cryptoppwin/include/cryptopp/tiger.h new file mode 100644 index 00000000..369f1ccd --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/tiger.h @@ -0,0 +1,61 @@ +// tiger.h - originally written and placed in the public domain by Wei Dai + +/// \file tiger.h +/// \brief Classes for the Tiger message digest +/// \details Crypto++ provides the original Tiger hash that was +/// submitted to the NESSIE project. The implementation is different +/// from the revised Tiger2 hash. +/// \sa Tiger and +/// Tiger: +/// A Fast New Cryptographic Hash Function +/// \since Crypto++ 2.1 + +#ifndef CRYPTOPP_TIGER_H +#define CRYPTOPP_TIGER_H + +#include "config.h" +#include "iterhash.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_TIGER_ASM 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Tiger message digest +/// \details Crypto++ provides the original Tiger hash that was +/// submitted to the NESSIE project. The implementation is different +/// from the revised Tiger2 hash. +/// \sa Tiger and +/// Tiger: +/// A Fast New Cryptographic Hash Function +/// \since Crypto++ 2.1 +class Tiger : public IteratedHashWithStaticTransform +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Tiger";} + std::string AlgorithmProvider() const; + + /// \brief Initialize state array + /// \param state the state of the hash + static void InitState(HashWordType *state); + /// \brief Operate the hash + /// \param digest the state of the hash + /// \param data the data to be digested + static void Transform(word64 *digest, const word64 *data); + /// \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() 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); + +protected: + static const word64 table[4*256+3]; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/trap.h b/third_party/cryptoppwin/include/cryptopp/trap.h new file mode 100644 index 00000000..2c2906b9 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/trap.h @@ -0,0 +1,163 @@ +// trap.h - written and placed in public domain by Jeffrey Walton. + +/// \file trap.h +/// \brief Debugging and diagnostic assertions +/// \details CRYPTOPP_ASSERT is the library's debugging and diagnostic +/// assertion. CRYPTOPP_ASSERT is enabled by CRYPTOPP_DEBUG, +/// DEBUG or _DEBUG. +/// \details CRYPTOPP_ASSERT raises a SIGTRAP (Unix) or calls +/// DebugBreak() (Windows). +/// \details CRYPTOPP_ASSERT is only in effect when the user requests a +/// debug configuration. NDEBUG (or failure to define it) does not +/// affect CRYPTOPP_ASSERT. +/// \since Crypto++ 5.6.5 +/// \sa DebugTrapHandler, Issue 277, +/// CVE-2016-7420 + +#ifndef CRYPTOPP_TRAP_H +#define CRYPTOPP_TRAP_H + +#include "config.h" + +#if defined(CRYPTOPP_DEBUG) +# include +# include +# if defined(UNIX_SIGNALS_AVAILABLE) +# include "ossig.h" +# elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(__CYGWIN__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); +# endif +#endif // CRYPTOPP_DEBUG + +// ************** run-time assertion *************** + +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) +/// \brief Debugging and diagnostic assertion +/// \details CRYPTOPP_ASSERT is the library's debugging and diagnostic +/// assertion. CRYPTOPP_ASSERT is enabled by the preprocessor macros +/// CRYPTOPP_DEBUG, DEBUG or _DEBUG. +/// \details CRYPTOPP_ASSERT raises a SIGTRAP (Unix) or calls +/// DebugBreak() (Windows). CRYPTOPP_ASSERT is only in effect +/// when the user explicitly requests a debug configuration. +/// \details If you want to ensure CRYPTOPP_ASSERT is inert, then do +/// not define CRYPTOPP_DEBUG, DEBUG or _DEBUG. +/// Avoiding the defines means CRYPTOPP_ASSERT is preprocessed into an +/// empty string. +/// \details The traditional Posix define NDEBUG has no effect on +/// CRYPTOPP_DEBUG, CRYPTOPP_ASSERT or DebugTrapHandler. +/// \details An example of using CRYPTOPP_ASSERT and DebugTrapHandler is shown +/// below. The library's test program, cryptest.exe (from test.cpp), +/// exercises the structure: +///
+///   \#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)
+///   static const DebugTrapHandler g_dummyHandler;
+///   \#endif
+///
+///   int main(int argc, char* argv[])
+///   {
+///      CRYPTOPP_ASSERT(argv != nullptr);
+///      ...
+///   }
+///  
+/// \since Crypto++ 5.6.5 +/// \sa DebugTrapHandler, SignalHandler, Issue 277, +/// CVE-2016-7420 +# define CRYPTOPP_ASSERT(exp) { ... } +#endif + +#if defined(CRYPTOPP_DEBUG) +# if defined(UNIX_SIGNALS_AVAILABLE) || defined(__CYGWIN__) +# define CRYPTOPP_ASSERT(exp) { \ + if (!(exp)) { \ + std::ostringstream oss; \ + oss << "Assertion failed: " << __FILE__ << "(" \ + << __LINE__ << "): " << __func__ \ + << std::endl; \ + std::cout << std::flush; \ + std::cerr << oss.str(); \ + raise(SIGTRAP); \ + } \ + } +# elif CRYPTOPP_DEBUG && defined(CRYPTOPP_WIN32_AVAILABLE) +# define CRYPTOPP_ASSERT(exp) { \ + if (!(exp)) { \ + std::ostringstream oss; \ + oss << "Assertion failed: " << __FILE__ << "(" \ + << __LINE__ << "): " << __FUNCTION__ \ + << std::endl; \ + std::cout << std::flush; \ + std::cerr << oss.str(); \ + if (IsDebuggerPresent()) {DebugBreak();} \ + } \ + } +# endif // Unix or Windows +#endif // CRYPTOPP_DEBUG + +// Remove CRYPTOPP_ASSERT in non-debug builds. +#ifndef CRYPTOPP_ASSERT +# define CRYPTOPP_ASSERT(exp) (void)0 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** SIGTRAP handler *************** + +#if (CRYPTOPP_DEBUG && defined(UNIX_SIGNALS_AVAILABLE)) || defined(CRYPTOPP_DOXYGEN_PROCESSING) +/// \brief Default SIGTRAP handler +/// \details DebugTrapHandler() can be used by a program to install an empty +/// SIGTRAP handler. If present, the handler ensures there is a signal +/// handler in place for SIGTRAP raised by +/// CRYPTOPP_ASSERT. If CRYPTOPP_ASSERT raises +/// SIGTRAP without a handler, then one of two things can +/// occur. First, the OS might allow the program to continue. Second, the OS +/// might terminate the program. OS X allows the program to continue, while +/// some Linuxes terminate the program. +/// \details If DebugTrapHandler detects another handler in place, then it will +/// not install a handler. This ensures a debugger can gain control of the +/// SIGTRAP signal without contention. It also allows multiple +/// DebugTrapHandler to be created without contentious or unusual behavior. +/// Though multiple DebugTrapHandler can be created, a program should only +/// create one, if needed. +/// \details A DebugTrapHandler is subject to C++ static initialization +/// [dis]order. If you need to install a handler and it must be installed +/// early, then reference the code associated with +/// CRYPTOPP_INIT_PRIORITY in cryptlib.cpp and cpu.cpp. +/// \details If you want to ensure CRYPTOPP_ASSERT is inert, then +/// do not define CRYPTOPP_DEBUG, DEBUG or +/// _DEBUG. Avoiding the defines means CRYPTOPP_ASSERT +/// is processed into ((void)0). +/// \details The traditional Posix define NDEBUG has no effect on +/// CRYPTOPP_DEBUG, CRYPTOPP_ASSERT or DebugTrapHandler. +/// \details An example of using \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT" and +/// DebugTrapHandler is shown below. The library's test program, +/// cryptest.exe (from test.cpp), exercises the structure: +///
+///   \#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)
+///   const DebugTrapHandler g_dummyHandler;
+///   \#endif
+///
+///   int main(int argc, char* argv[])
+///   {
+///      CRYPTOPP_ASSERT(argv != nullptr);
+///      ...
+///   }
+///  
+/// \since Crypto++ 5.6.5 +/// \sa \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", SignalHandler, Issue 277, +/// CVE-2016-7420 + +#if defined(CRYPTOPP_DOXYGEN_PROCESSING) +class DebugTrapHandler : public SignalHandler { }; +#else +typedef SignalHandler DebugTrapHandler; +#endif + +#endif // Linux, Unix and Documentation + +NAMESPACE_END + +#endif // CRYPTOPP_TRAP_H diff --git a/third_party/cryptoppwin/include/cryptopp/trunhash.h b/third_party/cryptoppwin/include/cryptopp/trunhash.h new file mode 100644 index 00000000..e659cc87 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/trunhash.h @@ -0,0 +1,63 @@ +// trunhash.h - originally written and placed in the public domain by Wei Dai + +/// \file trunhash.h +/// \brief Classes for truncated hashes + +#ifndef CRYPTOPP_TRUNHASH_H +#define CRYPTOPP_TRUNHASH_H + +#include "cryptlib.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Null hash +/// \details A null hash that conforms to HashTransformation interface +class NullHash : public HashTransformation +{ +public: + void Update(const byte *input, size_t length) + {CRYPTOPP_UNUSED(input);CRYPTOPP_UNUSED(length);} + unsigned int DigestSize() const + {return 0;} + void TruncatedFinal(byte *digest, size_t digestSize) + {CRYPTOPP_UNUSED(digest);CRYPTOPP_UNUSED(digestSize);} + bool TruncatedVerify(const byte *digest, size_t digestLength) + {CRYPTOPP_UNUSED(digest);CRYPTOPP_UNUSED(digestLength);return true;} +}; + +/// \brief Construct new HashModule with smaller digest size from an existing one +/// \tparam T HashTransformation derived class +template +class TruncatedHashTemplate : public HashTransformation +{ +public: + /// \brief Construct a TruncatedHashTemplate + TruncatedHashTemplate(T hm, unsigned int digestSize) + : m_hm(hm), m_digestSize(digestSize) {} + /// \brief Construct a TruncatedHashTemplate + TruncatedHashTemplate(const byte *key, size_t keyLength, unsigned int digestSize) + : m_hm(key, keyLength), m_digestSize(digestSize) {} + /// \brief Construct a TruncatedHashTemplate + TruncatedHashTemplate(size_t digestSize) + : m_digestSize(digestSize) {} + + void Restart() + {m_hm.Restart();} + void Update(const byte *input, size_t length) + {m_hm.Update(input, length);} + unsigned int DigestSize() const {return m_digestSize;} + void TruncatedFinal(byte *digest, size_t digestSize) + {m_hm.TruncatedFinal(digest, digestSize);} + bool TruncatedVerify(const byte *digest, size_t digestLength) + {return m_hm.TruncatedVerify(digest, digestLength);} + +private: + T m_hm; + unsigned int m_digestSize; +}; + +typedef TruncatedHashTemplate TruncatedHashModule; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/ttmac.h b/third_party/cryptoppwin/include/cryptopp/ttmac.h new file mode 100644 index 00000000..9d959875 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/ttmac.h @@ -0,0 +1,44 @@ +// ttmac.h - written and placed in the public domain by Kevin Springle + +/// \file ttmac.h +/// \brief Classes for the TTMAC message authentication code + +#ifndef CRYPTOPP_TTMAC_H +#define CRYPTOPP_TTMAC_H + +#include "seckey.h" +#include "iterhash.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief TTMAC message authentication code information +class CRYPTOPP_NO_VTABLE TTMAC_Base : public FixedKeyLength<20>, public IteratedHash +{ +public: + static std::string StaticAlgorithmName() {return std::string("Two-Track-MAC");} + CRYPTOPP_CONSTANT(DIGESTSIZE=20); + + unsigned int DigestSize() const {return DIGESTSIZE;}; + void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms); + void TruncatedFinal(byte *mac, size_t size); + +protected: + static void Transform (word32 *digest, const word32 *X, bool last); + void HashEndianCorrectedBlock(const word32 *data) {Transform(m_digest, data, false);} + void Init(); + word32* StateBuf() {return m_digest;} + + FixedSizeSecBlock m_digest; + FixedSizeSecBlock m_key; +}; + +/// \brief Two-Track-MAC message authentication code +/// \tparam T HashTransformation class +/// \details 160-bit MAC with 160-bit key +/// \sa MessageAuthenticationCode(), Two-Track-MAC +DOCUMENTED_TYPEDEF(MessageAuthenticationCodeFinal, TTMAC); + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/tweetnacl.h b/third_party/cryptoppwin/include/cryptopp/tweetnacl.h new file mode 100644 index 00000000..beafb752 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/tweetnacl.h @@ -0,0 +1,281 @@ +// tweetnacl.h - written and placed in the public domain by Jeffrey Walton + +/// \file nr.h +/// \brief Declarations for Bernstein's TweetNaCL +/// \details TweetNaCL is used to cross-validate the library's implementations. +/// The implementation itself is not optimized and kind of amusing. However +/// it serves a valuable purpose for cross-validation. +/// \details Don't use this in production. + +#ifndef TWEETNACL_H +#define TWEETNACL_H +#define crypto_auth_PRIMITIVE "hmacsha512256" +#define crypto_auth crypto_auth_hmacsha512256 +#define crypto_auth_verify crypto_auth_hmacsha512256_verify +#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES +#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES +#define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION +#define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION +#define crypto_auth_hmacsha512256_tweet_BYTES 32 +#define crypto_auth_hmacsha512256_tweet_KEYBYTES 32 +extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#define crypto_auth_hmacsha512256_tweet_VERSION "-" +#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet +#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify +#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES +#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES +#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION +#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet" +#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305" +#define crypto_box crypto_box_curve25519xsalsa20poly1305 +#define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open +#define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair +#define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm +#define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm +#define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm +#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES +#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES +#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES +#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES +#define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION +#define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION +#define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16 +extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-" +#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet +#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open +#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair +#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm +#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm +#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm +#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES +#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION +#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet" +#define crypto_core_PRIMITIVE "salsa20" +#define crypto_core crypto_core_salsa20 +#define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES +#define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES +#define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES +#define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES +#define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION +#define crypto_core_VERSION crypto_core_salsa20_VERSION +#define crypto_core_salsa20_tweet_OUTPUTBYTES 64 +#define crypto_core_salsa20_tweet_INPUTBYTES 16 +#define crypto_core_salsa20_tweet_KEYBYTES 32 +#define crypto_core_salsa20_tweet_CONSTBYTES 16 +extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#define crypto_core_salsa20_tweet_VERSION "-" +#define crypto_core_salsa20 crypto_core_salsa20_tweet +#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES +#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES +#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES +#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES +#define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION +#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet" +#define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32 +#define crypto_core_hsalsa20_tweet_INPUTBYTES 16 +#define crypto_core_hsalsa20_tweet_KEYBYTES 32 +#define crypto_core_hsalsa20_tweet_CONSTBYTES 16 +extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#define crypto_core_hsalsa20_tweet_VERSION "-" +#define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet +#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES +#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES +#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES +#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES +#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION +#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet" +#define crypto_hashblocks_PRIMITIVE "sha512" +#define crypto_hashblocks crypto_hashblocks_sha512 +#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES +#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES +#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION +#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION +#define crypto_hashblocks_sha512_tweet_STATEBYTES 64 +#define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128 +extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hashblocks_sha512_tweet_VERSION "-" +#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet +#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES +#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES +#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION +#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet" +#define crypto_hashblocks_sha256_tweet_STATEBYTES 32 +#define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64 +extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hashblocks_sha256_tweet_VERSION "-" +#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet +#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES +#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES +#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION +#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet" +#define crypto_hash_PRIMITIVE "sha512" +#define crypto_hash crypto_hash_sha512 +#define crypto_hash_BYTES crypto_hash_sha512_BYTES +#define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION +#define crypto_hash_VERSION crypto_hash_sha512_VERSION +#define crypto_hash_sha512_tweet_BYTES 64 +extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hash_sha512_tweet_VERSION "-" +#define crypto_hash_sha512 crypto_hash_sha512_tweet +#define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES +#define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION +#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet" +#define crypto_hash_sha256_tweet_BYTES 32 +extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hash_sha256_tweet_VERSION "-" +#define crypto_hash_sha256 crypto_hash_sha256_tweet +#define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES +#define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION +#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet" +#define crypto_onetimeauth_PRIMITIVE "poly1305" +#define crypto_onetimeauth crypto_onetimeauth_poly1305 +#define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify +#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES +#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES +#define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION +#define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION +#define crypto_onetimeauth_poly1305_tweet_BYTES 16 +#define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32 +extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#define crypto_onetimeauth_poly1305_tweet_VERSION "-" +#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet +#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify +#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES +#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES +#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION +#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet" +#define crypto_scalarmult_PRIMITIVE "curve25519" +#define crypto_scalarmult crypto_scalarmult_curve25519 +#define crypto_scalarmult_base crypto_scalarmult_curve25519_base +#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES +#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES +#define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION +#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION +#define crypto_scalarmult_curve25519_tweet_BYTES 32 +#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32 +extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *); +#define crypto_scalarmult_curve25519_tweet_VERSION "-" +#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet +#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base +#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES +#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES +#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION +#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet" +#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305" +#define crypto_secretbox crypto_secretbox_xsalsa20poly1305 +#define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open +#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES +#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES +#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES +#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES +#define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION +#define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION +#define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16 +extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-" +#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet +#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open +#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES +#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION +#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet" +#define crypto_sign_PRIMITIVE "ed25519" +#define crypto_sign crypto_sign_ed25519 +#define crypto_sign_open crypto_sign_ed25519_open +#define crypto_sign_keypair crypto_sign_ed25519_keypair +#define crypto_sign_BYTES crypto_sign_ed25519_BYTES +#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES +#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES +#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION +#define crypto_sign_VERSION crypto_sign_ed25519_VERSION +#define crypto_sign_ed25519_tweet_BYTES 64 +#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32 +#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64 +extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *); +#define crypto_sign_ed25519_tweet_VERSION "-" +#define crypto_sign_ed25519 crypto_sign_ed25519_tweet +#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open +#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair +#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES +#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES +#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES +#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION +#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet" +#define crypto_stream_PRIMITIVE "xsalsa20" +#define crypto_stream crypto_stream_xsalsa20 +#define crypto_stream_xor crypto_stream_xsalsa20_xor +#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES +#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES +#define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION +#define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION +#define crypto_stream_xsalsa20_tweet_KEYBYTES 32 +#define crypto_stream_xsalsa20_tweet_NONCEBYTES 24 +extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_stream_xsalsa20_tweet_VERSION "-" +#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet +#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor +#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES +#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES +#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION +#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet" +#define crypto_stream_salsa20_tweet_KEYBYTES 32 +#define crypto_stream_salsa20_tweet_NONCEBYTES 8 +extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_stream_salsa20_tweet_VERSION "-" +#define crypto_stream_salsa20 crypto_stream_salsa20_tweet +#define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor +#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES +#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES +#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION +#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet" +#define crypto_verify_PRIMITIVE "16" +#define crypto_verify crypto_verify_16 +#define crypto_verify_BYTES crypto_verify_16_BYTES +#define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION +#define crypto_verify_VERSION crypto_verify_16_VERSION +#define crypto_verify_16_tweet_BYTES 16 +extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *); +#define crypto_verify_16_tweet_VERSION "-" +#define crypto_verify_16 crypto_verify_16_tweet +#define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES +#define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION +#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet" +#define crypto_verify_32_tweet_BYTES 32 +extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *); +#define crypto_verify_32_tweet_VERSION "-" +#define crypto_verify_32 crypto_verify_32_tweet +#define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES +#define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION +#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet" +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/twofish.h b/third_party/cryptoppwin/include/cryptopp/twofish.h new file mode 100644 index 00000000..cf289028 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/twofish.h @@ -0,0 +1,64 @@ +// twofish.h - originally written and placed in the public domain by Wei Dai + +/// \file twofish.h +/// \brief Classes for the Twofish block cipher + +#ifndef CRYPTOPP_TWOFISH_H +#define CRYPTOPP_TWOFISH_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Twofish block cipher information +/// \since Crypto++ 3.1 +struct Twofish_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8>, FixedRounds<16> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Twofish";} +}; + +/// \brief Twofish block cipher +/// \sa Twofish +/// \since Crypto++ 3.1 +class Twofish : public Twofish_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + static word32 h0(word32 x, const word32 *key, unsigned int kLen); + static word32 h(word32 x, const word32 *key, unsigned int kLen); + + static const byte q[2][256]; + static const word32 mds[4][256]; + + FixedSizeSecBlock m_k; + FixedSizeSecBlock m_s; + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Twofish::Encryption TwofishEncryption; +typedef Twofish::Decryption TwofishDecryption; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/validate.h b/third_party/cryptoppwin/include/cryptopp/validate.h new file mode 100644 index 00000000..17474b52 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/validate.h @@ -0,0 +1,395 @@ +// validate.h - originally written and placed in the public domain by Wei Dai +// CryptoPP::Test namespace added by JW in February 2017 + +#ifndef CRYPTOPP_VALIDATE_H +#define CRYPTOPP_VALIDATE_H + +#include "cryptlib.h" +#include "misc.h" +#include "files.h" +#include "argnames.h" +#include "algparam.h" +#include "hex.h" + +#include +#include +#include +#include +#include + +NAMESPACE_BEGIN(CryptoPP) +NAMESPACE_BEGIN(Test) + +// A hint to help locate TestData/ and TestVectors/ after install. Due to +// execve the path can be malicious. If the path is ficticous then we move +// onto the next potential path. Also note we only read from the path; we +// never write through it. Storage for the string is in test.cpp. +extern std::string g_argvPathHint; + +bool ValidateAll(bool thorough); +bool TestSettings(); +bool TestOS_RNG(); +// bool TestSecRandom(); +bool TestRandomPool(); +#if !defined(NO_OS_DEPENDENCE) +bool TestAutoSeededX917(); +#endif +#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) +bool TestRDRAND(); +bool TestRDSEED(); +bool TestPadlockRNG(); +#endif +#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) +bool TestDARN(); +#endif +bool ValidateBaseCode(); +bool ValidateEncoder(); +bool ValidateCRC32(); +bool ValidateCRC32C(); +bool ValidateAdler32(); +bool ValidateMD2(); +bool ValidateMD4(); +bool ValidateMD5(); +bool ValidateSHA(); +bool ValidateSHA2(); +bool ValidateSHA3(); +bool ValidateSHAKE(); // output <= r, where r is blocksize +bool ValidateSHAKE_XOF(); // output > r, needs hand crafted tests +bool ValidateKeccak(); +bool ValidateTiger(); +bool ValidateRIPEMD(); +bool ValidatePanama(); +bool ValidateWhirlpool(); +bool ValidateLSH(); + +bool ValidateSM3(); +bool ValidateBLAKE2s(); +bool ValidateBLAKE2b(); +bool ValidatePoly1305(); +bool ValidateSipHash(); + +bool ValidateHMAC(); +bool ValidateTTMAC(); + +bool ValidateCipherModes(); +bool ValidatePBKDF(); +bool ValidateHKDF(); +bool ValidateScrypt(); + +bool ValidateDES(); +bool ValidateIDEA(); +bool ValidateSAFER(); +bool ValidateRC2(); +bool ValidateARC4(); + +bool ValidateRC5(); +bool ValidateBlowfish(); +bool ValidateBlowfishCompat(); +bool ValidateThreeWay(); +bool ValidateGOST(); +bool ValidateSHARK(); +bool ValidateSEAL(); +bool ValidateCAST(); +bool ValidateSquare(); +bool ValidateSKIPJACK(); +bool ValidateRC6(); +bool ValidateMARS(); +bool ValidateRijndael(); +bool ValidateTwofish(); +bool ValidateSerpent(); +bool ValidateSHACAL2(); +bool ValidateARIA(); +bool ValidateSIMECK(); +bool ValidateCHAM(); +bool ValidateHIGHT(); +bool ValidateLEA(); +bool ValidateSIMON(); +bool ValidateSPECK(); +bool ValidateCamellia(); + +bool ValidateHC128(); +bool ValidateHC256(); +bool ValidateRabbit(); +bool ValidateSalsa(); +bool ValidateChaCha(); +bool ValidateChaChaTLS(); +bool ValidateSosemanuk(); + +bool ValidateVMAC(); +bool ValidateCCM(); +bool ValidateGCM(); +bool ValidateXTS(); +bool ValidateCMAC(); + +bool ValidateBBS(); +bool ValidateDH(); +bool ValidateMQV(); +bool ValidateHMQV(); +bool ValidateFHMQV(); +bool ValidateRSA(); +bool ValidateElGamal(); +bool ValidateDLIES(); +bool ValidateNR(); +bool ValidateDSA(bool thorough); +bool ValidateLUC(); +bool ValidateLUC_DL(); +bool ValidateLUC_DH(); +bool ValidateXTR_DH(); +bool ValidateRabin(); +bool ValidateRW(); +bool ValidateECP(); +bool ValidateEC2N(); +bool ValidateECDSA(); +bool ValidateECDSA_RFC6979(); +bool ValidateECGDSA(bool thorough); +bool ValidateESIGN(); + +bool ValidateHashDRBG(); +bool ValidateHmacDRBG(); + +bool TestX25519(); +bool TestEd25519(); +bool ValidateX25519(); +bool ValidateEd25519(); +bool ValidateNaCl(); + +// If CRYPTOPP_DEBUG or CRYPTOPP_COVERAGE is in effect, then perform additional tests +#if (defined(CRYPTOPP_DEBUG) || defined(CRYPTOPP_COVERAGE)) && !defined(CRYPTOPP_IMPORTS) +# define CRYPTOPP_EXTENDED_VALIDATION 1 +#endif + +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +// http://github.com/weidai11/cryptopp/issues/92 +bool TestSecBlock(); +// http://github.com/weidai11/cryptopp/issues/64 +bool TestPolynomialMod2(); +// http://github.com/weidai11/cryptopp/issues/336 +bool TestIntegerBitops(); +// http://github.com/weidai11/cryptopp/issues/602 +bool TestIntegerOps(); +// http://github.com/weidai11/cryptopp/issues/360 +bool TestRounding(); +// http://github.com/weidai11/cryptopp/issues/242 +bool TestHuffmanCodes(); +// http://github.com/weidai11/cryptopp/issues/346 +bool TestASN1Parse(); +bool TestASN1Functions(); +// https://github.com/weidai11/cryptopp/pull/334 +bool TestStringSink(); +// Additional tests due to no coverage +bool TestCompressors(); +bool TestEncryptors(); +bool TestMersenne(); +bool TestSharing(); +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +bool TestAltivecOps(); +# endif +#endif + +class FixedRNG : public RandomNumberGenerator +{ +public: + FixedRNG(BufferedTransformation &source) : m_source(source) {} + + void GenerateBlock(byte *output, size_t size) + { + m_source.Get(output, size); + } + +private: + BufferedTransformation &m_source; +}; + +// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55 +inline std::string TimeToString(const time_t& t) +{ +#if (CRYPTOPP_MSC_VERSION >= 1400) + tm localTime; + char timeBuf[64]; + errno_t err; + + err = ::localtime_s(&localTime, &t); + CRYPTOPP_ASSERT(err == 0); + err = ::asctime_s(timeBuf, sizeof(timeBuf), &localTime); + CRYPTOPP_ASSERT(err == 0); + + std::string str(err == 0 ? timeBuf : ""); +#elif defined(__MINGW32__) || defined(__MINGW64__) + char* timeString = ::asctime(::localtime(&t)); + std::string str(timeString ? timeString : ""); +#elif (_POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || defined(_POSIX_SOURCE)) + tm localTime; + char timeBuf[64]; + char* timeString = ::asctime_r(::localtime_r(&t, &localTime), timeBuf); + std::string str(timeString ? timeString : ""); +#else + char* timeString = ::asctime(::localtime(&t)); + std::string str(timeString ? timeString : ""); +#endif + + // Cleanup whitespace + std::string::size_type pos = 0; + while (!str.empty() && std::isspace(str[str.length()-1])) + {str.erase(str.end()-1);} + while (!str.empty() && std::string::npos != (pos = str.find(" ", pos))) + {str.erase(pos, 1);} + + return str; +} + +// Coverity finding +template +inline T StringToValue(const std::string& str) +{ + std::istringstream iss(str); + + // Arbitrary, but we need to clear a Coverity finding TAINTED_SCALAR + if (iss.str().length() > 25) + throw InvalidArgument(str + "' is too long"); + + T value; + iss >> std::noskipws >> value; + + // Use fail(), not bad() + if (iss.fail()) + throw InvalidArgument(str + "' is not a value"); + + if (NON_NEGATIVE && value < 0) + throw InvalidArgument(str + "' is negative"); + + return value; +} + +// Coverity finding +template<> +inline int StringToValue(const std::string& str) +{ + Integer n(str.c_str()); + long l = n.ConvertToLong(); + + int r; + if (!SafeConvert(l, r)) + throw InvalidArgument(str + "' is not an integer value"); + + return r; +} + +inline std::string AddSeparator(std::string str) +{ + if (str.empty()) return ""; + const char last = str[str.length()-1]; + if (last != '/' && last != '\\') + return str + "/"; + return str; +} + +// Use CRYPTOPP_DATA_DIR last. The problem this sidesteps is, finding an +// old version of Crypto++ library in CRYPTOPP_DATA_DIR when the library +// has been staged in DESTDIR. Using CRYPTOPP_DATA_DIR first only works +// as expected when CRYPTOPP_DATA_DIR is empty before an install. We +// encountered this problem rather quickly during testing of Crypto++ 8.1 +// when Crypto++ 8.0 was installed locally. It took some time to realize +// where the old test data was coming from. +static std::string GetDataDir() +{ + std::ifstream file; + std::string name, filename = "TestData/usage.dat"; + +#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH + // Look in $ORIGIN/../share/. This is likely a Linux install directory. + name = AddSeparator(g_argvPathHint) + std::string("../share/cryptopp/") + filename; + file.open(name.c_str()); + if (file.is_open()) + return AddSeparator(g_argvPathHint) + std::string("../share/cryptopp/"); +#endif +#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH + // Look in current working directory + name = AddSeparator(g_argvPathHint) + filename; + file.open(name.c_str()); + if (file.is_open()) + return AddSeparator(g_argvPathHint); +#endif +#ifdef CRYPTOPP_DATA_DIR + // Honor CRYPTOPP_DATA_DIR. This is likely an install directory if it is not "./". + name = AddSeparator(CRYPTOPP_DATA_DIR) + filename; + file.open(name.c_str()); + if (file.is_open()) + return AddSeparator(CRYPTOPP_DATA_DIR); +#endif + return "./"; +} + +inline std::string DataDir(const std::string& filename) +{ + std::string name; + std::ifstream file; + +#if CRYPTOPP_CXX11_STATIC_INIT + static std::string path = AddSeparator(GetDataDir()); + name = path + filename; + file.open(name.c_str()); + if (file.is_open()) + return name; +#else + // Avoid static initialization problems + name = AddSeparator(GetDataDir()) + filename; + file.open(name.c_str()); + if (file.is_open()) + return name; +#endif + + // This will cause the expected exception in the caller + return filename; +} + +// Definition in test.cpp +RandomNumberGenerator& GlobalRNG(); + +// Definition in datatest.cpp +bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters=g_nullNameValuePairs, bool thorough=true); + +// Definitions in validat6.cpp +bool CryptoSystemValidate(PK_Decryptor &priv, PK_Encryptor &pub, bool thorough = false); +bool SimpleKeyAgreementValidate(SimpleKeyAgreementDomain &d); +bool AuthenticatedKeyAgreementWithRolesValidate(AuthenticatedKeyAgreementDomain &initiator, AuthenticatedKeyAgreementDomain &recipient); +bool AuthenticatedKeyAgreementValidate(AuthenticatedKeyAgreementDomain &d); +bool SignatureValidate(PK_Signer &priv, PK_Verifier &pub, bool thorough = false); + +// Miscellaneous PK definitions in validat6.cpp +// Key Agreement definitions in validat7.cpp +// Encryption and Decryption definitions in validat8.cpp +// Sign and Verify definitions in validat9.cpp + +bool ValidateECP(); +bool ValidateEC2N(); + +bool ValidateRSA_Encrypt(); +bool ValidateRSA_Sign(); + +bool ValidateLUC_Encrypt(); +bool ValidateLUC_Sign(); + +bool ValidateLUC_DL_Encrypt(); +bool ValidateLUC_DL_Sign(); + +bool ValidateRabin_Encrypt(); +bool ValidateRabin_Sign(); + +bool ValidateECP(); +bool ValidateECP_Agreement(); +bool ValidateECP_Encrypt(); +bool ValidateECP_Sign(); + +bool ValidateECP_Legacy_Encrypt(); +bool ValidateEC2N_Legacy_Encrypt(); +bool ValidateECP_NULLDigest_Encrypt(); + +bool ValidateEC2N(); +bool ValidateEC2N_Agreement(); +bool ValidateEC2N_Encrypt(); +bool ValidateEC2N_Sign(); + +NAMESPACE_END // Test +NAMESPACE_END // CryptoPP + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/vmac.h b/third_party/cryptoppwin/include/cryptopp/vmac.h new file mode 100644 index 00000000..2da1c7fc --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/vmac.h @@ -0,0 +1,91 @@ +// vmac.h - originally written and placed in the public domain by Wei Dai + +/// \file vmac.h +/// \brief Classes for the VMAC message authentication code +/// \since Crypto++ 5.5 + +#ifndef CRYPTOPP_VMAC_H +#define CRYPTOPP_VMAC_H + +#include "cryptlib.h" +#include "iterhash.h" +#include "seckey.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_VMAC_ASM 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief VMAC message authentication code base class +/// \since Crypto++ 5.5 +class VMAC_Base : public IteratedHashBase +{ +public: + std::string AlgorithmName() const {return std::string("VMAC(") + GetCipher().AlgorithmName() + ")-" + IntToString(DigestSize()*8);} + std::string AlgorithmProvider() const {return GetCipher().AlgorithmProvider();} + unsigned int IVSize() const {return GetCipher().BlockSize();} + unsigned int MinIVLength() const {return 1;} + void Resynchronize(const byte *nonce, int length=-1); + void GetNextIV(RandomNumberGenerator &rng, byte *IV); + unsigned int DigestSize() const {return m_is128 ? 16 : 8;}; + void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms); + void TruncatedFinal(byte *mac, size_t size); + unsigned int BlockSize() const {return m_L1KeyLength;} + ByteOrder GetByteOrder() const {return LITTLE_ENDIAN_ORDER;} + unsigned int OptimalDataAlignment() const; + +protected: + virtual BlockCipher & AccessCipher() =0; + virtual int DefaultDigestSize() const =0; + const BlockCipher & GetCipher() const {return const_cast(this)->AccessCipher();} + void HashEndianCorrectedBlock(const word64 *data); + size_t HashMultipleBlocks(const word64 *input, size_t length); + void Init() {} + word64* StateBuf() {return NULLPTR;} + word64* DataBuf() {return (word64 *)(void*)m_data();} + + void VHASH_Update_SSE2(const word64 *data, size_t blocksRemainingInWord64, int tagPart); + template + void VHASH_Update_Template(const word64 *data, size_t blockRemainingInWord128); + void VHASH_Update(const word64 *data, size_t blocksRemainingInWord128); + + CRYPTOPP_BLOCK_1(polyState, word64, (m_is128 ? 8 : 4)) + CRYPTOPP_BLOCK_2(nhKey, word64, m_L1KeyLength/sizeof(word64) + 2*m_is128) + CRYPTOPP_BLOCK_3(data, byte, m_L1KeyLength) + CRYPTOPP_BLOCK_4(l3Key, word64, (m_is128 ? 4 : 2)) + CRYPTOPP_BLOCK_5(nonce, byte, IVSize()) + CRYPTOPP_BLOCK_6(pad, byte, IVSize()) + CRYPTOPP_BLOCKS_END(6) + + bool m_is128, m_padCached, m_isFirstBlock; + unsigned int m_L1KeyLength; +}; + +/// \brief VMAC message authentication code +/// \tparam T_BlockCipher block cipher +/// \tparam T_DigestBitSize digest size, in bits +/// \details VMAC is a block cipher-based message authentication code algorithm +/// using a universal hash proposed by Ted Krovetz and Wei Dai in April 2007. The +/// algorithm was designed for high performance backed by a formal analysis. +/// \details The implementation is based on Ted Krovetz's public domain vmac.c +/// and draft-krovetz-vmac-01.txt. +/// \sa VMAC. +/// \since Crypto++ 5.5 +template +class VMAC : public SimpleKeyingInterfaceImpl > +{ +public: + static std::string StaticAlgorithmName() {return std::string("VMAC(") + T_BlockCipher::StaticAlgorithmName() + ")-" + IntToString(T_DigestBitSize);} + +private: + BlockCipher & AccessCipher() {return m_cipher;} + int DefaultDigestSize() const {return T_DigestBitSize/8;} + typename T_BlockCipher::Encryption m_cipher; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/wake.h b/third_party/cryptoppwin/include/cryptopp/wake.h new file mode 100644 index 00000000..616cbf1a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/wake.h @@ -0,0 +1,59 @@ +// wake.h - originally written and placed in the public domain by Wei Dai + +/// \file wake.h +/// \brief Classes for WAKE stream cipher + +#ifndef CRYPTOPP_WAKE_H +#define CRYPTOPP_WAKE_H + +#include "seckey.h" +#include "secblock.h" +#include "strciphr.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief WAKE stream cipher information +/// \tparam B Endianness of the stream cipher +/// \since Crypto++ 1.0 +template +struct WAKE_OFB_Info : public FixedKeyLength<32> +{ + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == LITTLE_ENDIAN_ORDER ? "WAKE-OFB-LE" : "WAKE-OFB-BE";} +}; + +class CRYPTOPP_NO_VTABLE WAKE_Base +{ +protected: + word32 M(word32 x, word32 y); + void GenKey(word32 k0, word32 k1, word32 k2, word32 k3); + + word32 t[257]; + word32 r3, r4, r5, r6; +}; + +/// \brief WAKE stream cipher operation +/// \tparam B Endianness of the stream cipher +/// \since Crypto++ 1.0 +template +class CRYPTOPP_NO_VTABLE WAKE_Policy : public AdditiveCipherConcretePolicy, protected WAKE_Base +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + // OFB + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + bool CipherIsRandomAccess() const {return false;} +}; + +/// \brief WAKE stream cipher +/// \tparam B Endianness of the stream cipher +/// \since Crypto++ 1.0 +template +struct WAKE_OFB : public WAKE_OFB_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, WAKE_OFB_Info > Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/whrlpool.h b/third_party/cryptoppwin/include/cryptopp/whrlpool.h new file mode 100644 index 00000000..d5b202fd --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/whrlpool.h @@ -0,0 +1,42 @@ +// whrlpool.h - originally modified by Kevin Springle from Paulo Barreto and Vincent Rijmen's +// public domain code, whirlpool.c. Updated to Whirlpool version 3.0, optimized +// and SSE version added by WD. All modifications are placed in the public domain. + +#ifndef CRYPTOPP_WHIRLPOOL_H +#define CRYPTOPP_WHIRLPOOL_H + +/// \file whrlpool.h +/// \brief Classes for the Whirlpool message digest +/// \details Crypto++ provides version 3.0 of the Whirlpool algorithm. +/// This version of the algorithm was submitted for ISO standardization. + +#include "config.h" +#include "iterhash.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_WHIRLPOOL_ASM 1 +#endif + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Whirlpool message digest +/// \details Crypto++ provides version 3.0 of the Whirlpool algorithm. +/// This version of the algorithm was submitted for ISO standardization. +/// \since Crypto++ 5.2 +/// \sa Whirlpool +class Whirlpool : public IteratedHashWithStaticTransform +{ +public: + CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Whirlpool";} + std::string AlgorithmProvider() const; + + static void InitState(HashWordType *state); + static void Transform(word64 *digest, const word64 *data); + void TruncatedFinal(byte *hash, size_t size); +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/words.h b/third_party/cryptoppwin/include/cryptopp/words.h new file mode 100644 index 00000000..a7ac1995 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/words.h @@ -0,0 +1,225 @@ +// words.h - originally written and placed in the public domain by Wei Dai + +/// \file words.h +/// \brief Support functions for word operations + +#ifndef CRYPTOPP_WORDS_H +#define CRYPTOPP_WORDS_H + +#include "config.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Count the number of words +/// \param x word array +/// \param n size of the word array, in elements +/// \return number of words used in the array. +/// \details CountWords counts the number of words in a word array. +/// Leading 0-words are not included in the count. +/// \since Crypto++ 1.0 +inline size_t CountWords(const word *x, size_t n) +{ + while (n && x[n-1]==0) + n--; + return n; +} + +/// \brief Set the value of words +/// \param r word array +/// \param a value +/// \param n size of the word array, in elements +/// \details SetWords sets all elements in the word array to the +/// specified value. +/// \since Crypto++ 1.0 +inline void SetWords(word *r, word a, size_t n) +{ + for (size_t i=0; i> (WORD_BITS-shiftBits); + } + return carry; +} + +/// \brief Right shift word array +/// \param r word array +/// \param n size of the word array, in elements +/// \param shiftBits number of bits to shift +/// \return word shifted out +/// \details ShiftWordsRightByBits shifts the word array shight by +/// shiftBits. ShiftWordsRightByBits shifts bits out on the right. +/// \note shiftBits must be less than WORD_BITS. +/// \since Crypto++ 1.0 +inline word ShiftWordsRightByBits(word *r, size_t n, unsigned int shiftBits) +{ + CRYPTOPP_ASSERT (shiftBits0; i--) + { + u = r[i-1]; + r[i-1] = (u >> shiftBits) | carry; + carry = u << (WORD_BITS-shiftBits); + } + return carry; +} + +/// \brief Left shift word array +/// \param r word array +/// \param n size of the word array, in elements +/// \param shiftWords number of words to shift +/// \details ShiftWordsLeftByWords shifts the word array left by +/// shiftWords. ShiftWordsLeftByWords shifts bits out on the left; +/// it does not extend the array. +/// \since Crypto++ 1.0 +inline void ShiftWordsLeftByWords(word *r, size_t n, size_t shiftWords) +{ + shiftWords = STDMIN(shiftWords, n); + if (shiftWords) + { + for (size_t i=n-1; i>=shiftWords; i--) + r[i] = r[i-shiftWords]; + SetWords(r, 0, shiftWords); + } +} + +/// \brief Right shift word array +/// \param r word array +/// \param n size of the word array, in elements +/// \param shiftWords number of words to shift +/// \details ShiftWordsRightByWords shifts the word array right by +/// shiftWords. ShiftWordsRightByWords shifts bits out on the right. +/// \since Crypto++ 1.0 +inline void ShiftWordsRightByWords(word *r, size_t n, size_t shiftWords) +{ + shiftWords = STDMIN(shiftWords, n); + if (shiftWords) + { + for (size_t i=0; i+shiftWordsdraft-ietf-curdle-pkix. +/// \details If you have a little endian array and you want to wrap it in +/// an Integer using big endian then you can perform the following: +///
Integer x(my_arr, SECRET_KEYLENGTH, UNSIGNED, LITTLE_ENDIAN_ORDER);
+/// \sa Andrew Moon's x22519 GitHub curve25519-donna, +/// ed22519 GitHub ed25519-donna, and +/// draft-ietf-curdle-pkix +/// \since Crypto++ 8.0 + +#ifndef CRYPTOPP_XED25519_H +#define CRYPTOPP_XED25519_H + +#include "cryptlib.h" +#include "pubkey.h" +#include "oids.h" + +NAMESPACE_BEGIN(CryptoPP) + +class Integer; +struct ed25519Signer; +struct ed25519Verifier; + +// ******************** x25519 Agreement ************************* // + +/// \brief x25519 with key validation +/// \since Crypto++ 8.0 +class x25519 : public SimpleKeyAgreementDomain, public CryptoParameters, public PKCS8PrivateKey +{ +public: + /// \brief Size of the private key + /// \details SECRET_KEYLENGTH is the size of the private key, in bytes. + CRYPTOPP_CONSTANT(SECRET_KEYLENGTH = 32); + /// \brief Size of the public key + /// \details PUBLIC_KEYLENGTH is the size of the public key, in bytes. + CRYPTOPP_CONSTANT(PUBLIC_KEYLENGTH = 32); + /// \brief Size of the shared key + /// \details SHARED_KEYLENGTH is the size of the shared key, in bytes. + CRYPTOPP_CONSTANT(SHARED_KEYLENGTH = 32); + + virtual ~x25519() {} + + /// \brief Create a x25519 object + /// \details This constructor creates an empty x25519 object. It is + /// intended for use in loading existing parameters, like CryptoBox + /// parameters. If you are performing key agreement you should use a + /// constructor that generates random parameters on construction. + x25519() {} + + /// \brief Create a x25519 object + /// \param y public key + /// \param x private key + /// \details This constructor creates a x25519 object using existing parameters. + /// \note The public key is not validated. + x25519(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]); + + /// \brief Create a x25519 object + /// \param x private key + /// \details This constructor creates a x25519 object using existing parameters. + /// The public key is calculated from the private key. + x25519(const byte x[SECRET_KEYLENGTH]); + + /// \brief Create a x25519 object + /// \param y public key + /// \param x private key + /// \details This constructor creates a x25519 object using existing parameters. + /// \note The public key is not validated. + x25519(const Integer &y, const Integer &x); + + /// \brief Create a x25519 object + /// \param x private key + /// \details This constructor creates a x25519 object using existing parameters. + /// The public key is calculated from the private key. + x25519(const Integer &x); + + /// \brief Create a x25519 object + /// \param rng RandomNumberGenerator derived class + /// \details This constructor creates a new x25519 using the random number generator. + x25519(RandomNumberGenerator &rng); + + /// \brief Create a x25519 object + /// \param params public and private key + /// \details This constructor creates a x25519 object using existing parameters. + /// The params can be created with Save. + /// \note The public key is not validated. + x25519(BufferedTransformation ¶ms); + + /// \brief Create a x25519 object + /// \param oid an object identifier + /// \details This constructor creates a new x25519 using the specified OID. The public + /// and private points are uninitialized. + x25519(const OID &oid); + + /// \brief Clamp a private key + /// \param x private key + /// \details ClampKeys() clamps a private key and then regenerates the + /// public key from the private key. + void ClampKey(byte x[SECRET_KEYLENGTH]) const; + + /// \brief Determine if private key is clamped + /// \param x private key + bool IsClamped(const byte x[SECRET_KEYLENGTH]) const; + + /// \brief Test if a key has small order + /// \param y public key + bool IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const; + + /// \brief Get the Object Identifier + /// \return the Object Identifier + /// \details The default OID is from RFC 8410 using id-X25519. + /// The default private key format is RFC 5208. + OID GetAlgorithmID() const { + return m_oid.Empty() ? ASN1::X25519() : m_oid; + } + + /// \brief Set the Object Identifier + /// \param oid the new Object Identifier + void SetAlgorithmID(const OID& oid) { + m_oid = oid; + } + + // CryptoParameters + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // CryptoParameters + CryptoParameters & AccessCryptoParameters() {return *this;} + + /// \brief DER encode ASN.1 object + /// \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 + /// subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-X25519. + /// The default private key format is RFC 5208, which is the old format. + /// The old format provides the best interop, and keys will work + /// with OpenSSL. + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Save(BufferedTransformation &bt) const { + DEREncode(bt, 0); + } + + /// \brief DER encode ASN.1 object + /// \param bt BufferedTransformation object + /// \param v1 flag indicating v1 + /// \details Save() will write the OID associated with algorithm or scheme. + /// In the case of public and private keys, this function writes the + /// subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-X25519. + /// The default private key format is RFC 5208. + /// \details v1 means INTEGER 0 is written. INTEGER 0 means + /// RFC 5208 format, which is the old format. The old format provides + /// the best interop, and keys will work with OpenSSL. The other + /// option uses INTEGER 1. INTEGER 1 means RFC 5958 format, + /// which is the new format. + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Save(BufferedTransformation &bt, bool v1) const { + DEREncode(bt, v1 ? 0 : 1); + } + + /// \brief BER decode ASN.1 object + /// \param bt BufferedTransformation object + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Load(BufferedTransformation &bt) { + BERDecode(bt); + } + + // PKCS8PrivateKey + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const { DEREncode(bt, 0); } + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; + + /// \brief DER encode ASN.1 object + /// \param bt BufferedTransformation object + /// \param version indicates version + /// \details DEREncode() will write the OID associated with algorithm or + /// scheme. In the case of public and private keys, this function writes + /// the subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-X25519. + /// The default private key format is RFC 5208. + /// \details The value of version is written as the INTEGER. INTEGER 0 means + /// RFC 5208 format, which is the old format. The old format provides + /// the best interop, and keys will work with OpenSSL. The INTEGER 1 + /// means RFC 5958 format, which is the new format. + void DEREncode(BufferedTransformation &bt, int version) const; + + /// \brief Determine if OID is valid for this object + /// \details BERDecodeAndCheckAlgorithmID() parses the OID from + /// bt and determines if it valid for this object. The + /// problem in practice is there are multiple OIDs available to + /// denote curve25519 operations. The OIDs include an old GNU + /// OID used by SSH, OIDs specified in draft-josefsson-pkix-newcurves, + /// and OIDs specified in draft-ietf-curdle-pkix. + /// \details By default BERDecodeAndCheckAlgorithmID() accepts an + /// OID set by the user, ASN1::curve25519() and ASN1::X25519(). + /// ASN1::curve25519() is generic and says "this key is valid for + /// curve25519 operations". ASN1::X25519() is specific and says + /// "this key is valid for x25519 key exchange." + void BERDecodeAndCheckAlgorithmID(BufferedTransformation& bt); + + // DL_PrivateKey + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms); + + // SimpleKeyAgreementDomain + unsigned int AgreedValueLength() const {return SHARED_KEYLENGTH;} + unsigned int PrivateKeyLength() const {return SECRET_KEYLENGTH;} + unsigned int PublicKeyLength() const {return PUBLIC_KEYLENGTH;} + + // SimpleKeyAgreementDomain + void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const; + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const; + bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const; + +protected: + // Create a public key from a private key + void SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const; + +protected: + FixedSizeSecBlock m_sk; + FixedSizeSecBlock m_pk; + OID m_oid; // preferred OID +}; + +// ****************** ed25519 Signer *********************** // + +/// \brief ed25519 message accumulator +/// \details ed25519 buffers the entire message, and does not +/// digest the message incrementally. You should be careful with +/// large messages like files on-disk. The behavior is by design +/// because Bernstein feels small messages should be authenticated; +/// and larger messages will be digested by the application. +/// \details The accumulator is used for signing and verification. +/// The first 64-bytes of storage is reserved for the signature. +/// During signing the signature storage is unused. During +/// verification the first 64 bytes holds the signature. The +/// signature is provided by the PK_Verifier framework and the +/// call to PK_Signer::InputSignature. Member functions data() +/// and size() refer to the accumulated message. Member function +/// signature() refers to the signature with an implicit size of +/// SIGNATURE_LENGTH bytes. +/// \details Applications which digest large messages, like an ISO +/// disk file, should take care because the design effectively +/// disgorges the format operation from the signing operation. +/// Put another way, be careful to ensure what you are signing is +/// is in fact a digest of the intended message, and not a different +/// message digest supplied by an attacker. +struct ed25519_MessageAccumulator : public PK_MessageAccumulator +{ + CRYPTOPP_CONSTANT(RESERVE_SIZE=2048+64); + CRYPTOPP_CONSTANT(SIGNATURE_LENGTH=64); + + /// \brief Create a message accumulator + ed25519_MessageAccumulator() { + Restart(); + } + + /// \brief Create a message accumulator + /// \details ed25519 does not use a RNG. You can safely use + /// NullRNG() because IsProbablistic returns false. + ed25519_MessageAccumulator(RandomNumberGenerator &rng) { + CRYPTOPP_UNUSED(rng); Restart(); + } + + /// \brief Add data to the accumulator + /// \param msg pointer to the data to accumulate + /// \param len the size of the data, in bytes + void Update(const byte* msg, size_t len) { + if (msg && len) + m_msg.insert(m_msg.end(), msg, msg+len); + } + + /// \brief Reset the accumulator + void Restart() { + m_msg.reserve(RESERVE_SIZE); + m_msg.resize(SIGNATURE_LENGTH); + } + + /// \brief Retrieve pointer to signature buffer + /// \return pointer to signature buffer + byte* signature() { + return &m_msg[0]; + } + + /// \brief Retrieve pointer to signature buffer + /// \return pointer to signature buffer + const byte* signature() const { + return &m_msg[0]; + } + + /// \brief Retrieve pointer to data buffer + /// \return pointer to data buffer + const byte* data() const { + return &m_msg[0]+SIGNATURE_LENGTH; + } + + /// \brief Retrieve size of data buffer + /// \return size of the data buffer, in bytes + size_t size() const { + return m_msg.size()-SIGNATURE_LENGTH; + } + +protected: + // TODO: Find an equivalent Crypto++ structure. + std::vector > m_msg; +}; + +/// \brief Ed25519 private key +/// \details ed25519PrivateKey is somewhat of a hack. It needed to +/// provide DL_PrivateKey interface to fit into the existing +/// framework, but it lacks a lot of the internals of a true +/// DL_PrivateKey. The missing pieces include GroupParameters +/// and Point, which provide the low level field operations +/// found in traditional implementations like NIST curves over +/// prime and binary fields. +/// \details ed25519PrivateKey is also unusual because the +/// class members of interest are byte arrays and not Integers. +/// In addition, the byte arrays are little-endian meaning +/// LSB is at element 0 and the MSB is at element 31. +/// If you call GetPrivateExponent() then the little-endian byte +/// array is converted to a big-endian Integer() so it can be +/// returned the way a caller expects. And calling +/// SetPrivateExponent performs a similar internal conversion. +/// \since Crypto++ 8.0 +struct ed25519PrivateKey : public PKCS8PrivateKey +{ + /// \brief Size of the private key + /// \details SECRET_KEYLENGTH is the size of the private key, in bytes. + CRYPTOPP_CONSTANT(SECRET_KEYLENGTH = 32); + /// \brief Size of the public key + /// \details PUBLIC_KEYLENGTH is the size of the public key, in bytes. + CRYPTOPP_CONSTANT(PUBLIC_KEYLENGTH = 32); + /// \brief Size of the signature + /// \details SIGNATURE_LENGTH is the size of the signature, in bytes. + /// ed25519 is a DL-based signature scheme. The signature is the + /// concatenation of r || s. + CRYPTOPP_CONSTANT(SIGNATURE_LENGTH = 64); + + virtual ~ed25519PrivateKey() {} + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // GroupParameters + OID GetAlgorithmID() const { + return m_oid.Empty() ? ASN1::Ed25519() : m_oid; + } + + /// \brief DER encode ASN.1 object + /// \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 + /// subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-Ed25519. + /// The default private key format is RFC 5208, which is the old format. + /// The old format provides the best interop, and keys will work + /// with OpenSSL. + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Save(BufferedTransformation &bt) const { + DEREncode(bt, 0); + } + + /// \brief DER encode ASN.1 object + /// \param bt BufferedTransformation object + /// \param v1 flag indicating v1 + /// \details Save() will write the OID associated with algorithm or scheme. + /// In the case of public and private keys, this function writes the + /// subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-Ed25519. + /// The default private key format is RFC 5208. + /// \details v1 means INTEGER 0 is written. INTEGER 0 means + /// RFC 5208 format, which is the old format. The old format provides + /// the best interop, and keys will work with OpenSSL. The other + /// option uses INTEGER 1. INTEGER 1 means RFC 5958 format, + /// which is the new format. + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Save(BufferedTransformation &bt, bool v1) const { + DEREncode(bt, v1 ? 0 : 1); + } + + /// \brief BER decode ASN.1 object + /// \param bt BufferedTransformation object + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Load(BufferedTransformation &bt) { + BERDecode(bt); + } + + /// \brief Initializes a public key from this key + /// \param pub reference to a public key + void MakePublicKey(PublicKey &pub) const; + + // PKCS8PrivateKey + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const { DEREncode(bt, 0); } + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; + + /// \brief DER encode ASN.1 object + /// \param bt BufferedTransformation object + /// \param version indicates version + /// \details DEREncode() will write the OID associated with algorithm or + /// scheme. In the case of public and private keys, this function writes + /// the subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-X25519. + /// The default private key format is RFC 5208. + /// \details The value of version is written as the INTEGER. INTEGER 0 means + /// RFC 5208 format, which is the old format. The old format provides + /// the best interop, and keys will work with OpenSSL. The INTEGER 1 + /// means RFC 5958 format, which is the new format. + void DEREncode(BufferedTransformation &bt, int version) const; + + /// \brief Determine if OID is valid for this object + /// \details BERDecodeAndCheckAlgorithmID() parses the OID from + /// bt and determines if it valid for this object. The + /// problem in practice is there are multiple OIDs available to + /// denote curve25519 operations. The OIDs include an old GNU + /// OID used by SSH, OIDs specified in draft-josefsson-pkix-newcurves, + /// and OIDs specified in draft-ietf-curdle-pkix. + /// \details By default BERDecodeAndCheckAlgorithmID() accepts an + /// OID set by the user, ASN1::curve25519() and ASN1::Ed25519(). + /// ASN1::curve25519() is generic and says "this key is valid for + /// curve25519 operations". ASN1::Ed25519() is specific and says + /// "this key is valid for ed25519 signing." + void BERDecodeAndCheckAlgorithmID(BufferedTransformation& bt); + + // PKCS8PrivateKey + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms); + void SetPrivateExponent(const byte x[SECRET_KEYLENGTH]); + void SetPrivateExponent(const Integer &x); + const Integer& GetPrivateExponent() const; + + /// \brief Test if a key has small order + /// \param y public key + bool IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const; + + /// \brief Retrieve private key byte array + /// \return the private key byte array + /// \details GetPrivateKeyBytePtr() is used by signing code to call ed25519_sign. + const byte* GetPrivateKeyBytePtr() const { + return m_sk.begin(); + } + + /// \brief Retrieve public key byte array + /// \return the public key byte array + /// \details GetPublicKeyBytePtr() is used by signing code to call ed25519_sign. + const byte* GetPublicKeyBytePtr() const { + return m_pk.begin(); + } + +protected: + // Create a public key from a private key + void SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const; + +protected: + FixedSizeSecBlock m_sk; + FixedSizeSecBlock m_pk; + OID m_oid; // preferred OID + mutable Integer m_x; // for DL_PrivateKey +}; + +/// \brief Ed25519 signature algorithm +/// \since Crypto++ 8.0 +struct ed25519Signer : public PK_Signer +{ + /// \brief Size of the private key + /// \details SECRET_KEYLENGTH is the size of the private key, in bytes. + CRYPTOPP_CONSTANT(SECRET_KEYLENGTH = 32); + /// \brief Size of the public key + /// \details PUBLIC_KEYLENGTH is the size of the public key, in bytes. + CRYPTOPP_CONSTANT(PUBLIC_KEYLENGTH = 32); + /// \brief Size of the signature + /// \details SIGNATURE_LENGTH is the size of the signature, in bytes. + /// ed25519 is a DL-based signature scheme. The signature is the + /// concatenation of r || s. + CRYPTOPP_CONSTANT(SIGNATURE_LENGTH = 64); + typedef Integer Element; + + virtual ~ed25519Signer() {} + + /// \brief Create an ed25519Signer object + ed25519Signer() {} + + /// \brief Create an ed25519Signer object + /// \param y public key + /// \param x private key + /// \details This constructor creates an ed25519Signer object using existing parameters. + /// \note The public key is not validated. + ed25519Signer(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]); + + /// \brief Create an ed25519Signer object + /// \param x private key + /// \details This constructor creates an ed25519Signer object using existing parameters. + /// The public key is calculated from the private key. + ed25519Signer(const byte x[SECRET_KEYLENGTH]); + + /// \brief Create an ed25519Signer object + /// \param y public key + /// \param x private key + /// \details This constructor creates an ed25519Signer object using existing parameters. + /// \note The public key is not validated. + ed25519Signer(const Integer &y, const Integer &x); + + /// \brief Create an ed25519Signer object + /// \param x private key + /// \details This constructor creates an ed25519Signer object using existing parameters. + /// The public key is calculated from the private key. + ed25519Signer(const Integer &x); + + /// \brief Create an ed25519Signer object + /// \param key PKCS8 private key + /// \details This constructor creates an ed25519Signer object using existing private key. + /// \note The keys are not validated. + /// \since Crypto++ 8.6 + ed25519Signer(const PKCS8PrivateKey &key); + + /// \brief Create an ed25519Signer object + /// \param rng RandomNumberGenerator derived class + /// \details This constructor creates a new ed25519Signer using the random number generator. + ed25519Signer(RandomNumberGenerator &rng); + + /// \brief Create an ed25519Signer object + /// \param params public and private key + /// \details This constructor creates an ed25519Signer object using existing parameters. + /// The params can be created with Save. + /// \note The public key is not validated. + ed25519Signer(BufferedTransformation ¶ms); + + // DL_ObjectImplBase + /// \brief Retrieves a reference to a Private Key + /// \details AccessKey() retrieves a non-const reference to a private key. + PrivateKey& AccessKey() { return m_key; } + PrivateKey& AccessPrivateKey() { return m_key; } + + /// \brief Retrieves a reference to a Private Key + /// \details AccessKey() retrieves a const reference to a private key. + const PrivateKey& GetKey() const { return m_key; } + const PrivateKey& GetPrivateKey() const { return m_key; } + + // DL_SignatureSchemeBase + size_t SignatureLength() const { return SIGNATURE_LENGTH; } + size_t MaxRecoverableLength() const { return 0; } + size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const { + CRYPTOPP_UNUSED(signatureLength); return 0; + } + + bool IsProbabilistic() const { return false; } + bool AllowNonrecoverablePart() const { return false; } + bool RecoverablePartFirst() const { return false; } + + PK_MessageAccumulator* NewSignatureAccumulator(RandomNumberGenerator &rng) const { + return new ed25519_MessageAccumulator(rng); + } + + void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const { + CRYPTOPP_UNUSED(messageAccumulator); CRYPTOPP_UNUSED(recoverableMessage); + CRYPTOPP_UNUSED(recoverableMessageLength); + throw NotImplemented("ed25519Signer: this object does not support recoverable messages"); + } + + size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const; + + /// \brief Sign a stream + /// \param rng a RandomNumberGenerator derived class + /// \param stream an std::istream derived class + /// \param signature a block of bytes for the signature + /// \return actual signature length + /// \details SignStream() handles large streams. The Stream functions were added to + /// ed25519 for signing and verifying files that are too large for a memory allocation. + /// The functions are not present in other library signers and verifiers. + /// \details ed25519 is a deterministic signature scheme. IsProbabilistic() + /// returns false and the random number generator can be NullRNG(). + /// \pre COUNTOF(signature) == MaxSignatureLength() + /// \since Crypto++ 8.1 + size_t SignStream (RandomNumberGenerator &rng, std::istream& stream, byte *signature) const; + +protected: + ed25519PrivateKey m_key; +}; + +// ****************** ed25519 Verifier *********************** // + +/// \brief Ed25519 public key +/// \details ed25519PublicKey is somewhat of a hack. It needed to +/// provide DL_PublicKey interface to fit into the existing +/// framework, but it lacks a lot of the internals of a true +/// DL_PublicKey. The missing pieces include GroupParameters +/// and Point, which provide the low level field operations +/// found in traditional implementations like NIST curves over +/// prime and binary fields. +/// \details ed25519PublicKey is also unusual because the +/// class members of interest are byte arrays and not Integers. +/// In addition, the byte arrays are little-endian meaning +/// LSB is at element 0 and the MSB is at element 31. +/// If you call GetPublicElement() then the little-endian byte +/// array is converted to a big-endian Integer() so it can be +/// returned the way a caller expects. And calling +/// SetPublicElement() performs a similar internal conversion. +/// \since Crypto++ 8.0 +struct ed25519PublicKey : public X509PublicKey +{ + /// \brief Size of the public key + /// \details PUBLIC_KEYLENGTH is the size of the public key, in bytes. + CRYPTOPP_CONSTANT(PUBLIC_KEYLENGTH = 32); + typedef Integer Element; + + virtual ~ed25519PublicKey() {} + + OID GetAlgorithmID() const { + return m_oid.Empty() ? ASN1::Ed25519() : m_oid; + } + + /// \brief DER encode ASN.1 object + /// \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 + /// subjectPublicKeyInfo parts. + /// \details The default OID is from RFC 8410 using id-X25519. + /// The default private key format is RFC 5208, which is the old format. + /// The old format provides the best interop, and keys will work + /// with OpenSSL. + void Save(BufferedTransformation &bt) const { + DEREncode(bt); + } + + /// \brief BER decode ASN.1 object + /// \param bt BufferedTransformation object + /// \sa RFC 5958, Asymmetric + /// Key Packages + void Load(BufferedTransformation &bt) { + BERDecode(bt); + } + + // X509PublicKey + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePublicKey(BufferedTransformation &bt) const; + + /// \brief Determine if OID is valid for this object + /// \details BERDecodeAndCheckAlgorithmID() parses the OID from + /// bt and determines if it valid for this object. The + /// problem in practice is there are multiple OIDs available to + /// denote curve25519 operations. The OIDs include an old GNU + /// OID used by SSH, OIDs specified in draft-josefsson-pkix-newcurves, + /// and OIDs specified in draft-ietf-curdle-pkix. + /// \details By default BERDecodeAndCheckAlgorithmID() accepts an + /// OID set by the user, ASN1::curve25519() and ASN1::Ed25519(). + /// ASN1::curve25519() is generic and says "this key is valid for + /// curve25519 operations". ASN1::Ed25519() is specific and says + /// "this key is valid for ed25519 signing." + void BERDecodeAndCheckAlgorithmID(BufferedTransformation& bt); + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // DL_PublicKey + void SetPublicElement(const byte y[PUBLIC_KEYLENGTH]); + void SetPublicElement(const Element &y); + const Element& GetPublicElement() const; + + /// \brief Retrieve public key byte array + /// \return the public key byte array + /// \details GetPublicKeyBytePtr() is used by signing code to call ed25519_sign. + const byte* GetPublicKeyBytePtr() const { + return m_pk.begin(); + } + +protected: + FixedSizeSecBlock m_pk; + OID m_oid; // preferred OID + mutable Integer m_y; // for DL_PublicKey +}; + +/// \brief Ed25519 signature verification algorithm +/// \since Crypto++ 8.0 +struct ed25519Verifier : public PK_Verifier +{ + CRYPTOPP_CONSTANT(PUBLIC_KEYLENGTH = 32); + CRYPTOPP_CONSTANT(SIGNATURE_LENGTH = 64); + typedef Integer Element; + + virtual ~ed25519Verifier() {} + + /// \brief Create an ed25519Verifier object + ed25519Verifier() {} + + /// \brief Create an ed25519Verifier object + /// \param y public key + /// \details This constructor creates an ed25519Verifier object using existing parameters. + /// \note The public key is not validated. + ed25519Verifier(const byte y[PUBLIC_KEYLENGTH]); + + /// \brief Create an ed25519Verifier object + /// \param y public key + /// \details This constructor creates an ed25519Verifier object using existing parameters. + /// \note The public key is not validated. + ed25519Verifier(const Integer &y); + + /// \brief Create an ed25519Verifier object + /// \param key X509 public key + /// \details This constructor creates an ed25519Verifier object using an existing public key. + /// \note The public key is not validated. + /// \since Crypto++ 8.6 + ed25519Verifier(const X509PublicKey &key); + + /// \brief Create an ed25519Verifier object + /// \param params public and private key + /// \details This constructor creates an ed25519Verifier object using existing parameters. + /// The params can be created with Save. + /// \note The public key is not validated. + ed25519Verifier(BufferedTransformation ¶ms); + + /// \brief Create an ed25519Verifier object + /// \param signer ed25519 signer object + /// \details This constructor creates an ed25519Verifier object using existing parameters. + /// The params can be created with Save. + /// \note The public key is not validated. + ed25519Verifier(const ed25519Signer& signer); + + // DL_ObjectImplBase + /// \brief Retrieves a reference to a Public Key + /// \details AccessKey() retrieves a non-const reference to a public key. + PublicKey& AccessKey() { return m_key; } + PublicKey& AccessPublicKey() { return m_key; } + + /// \brief Retrieves a reference to a Public Key + /// \details GetKey() retrieves a const reference to a public key. + const PublicKey& GetKey() const { return m_key; } + const PublicKey& GetPublicKey() const { return m_key; } + + // DL_SignatureSchemeBase + size_t SignatureLength() const { return SIGNATURE_LENGTH; } + size_t MaxRecoverableLength() const { return 0; } + size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const { + CRYPTOPP_UNUSED(signatureLength); return 0; + } + + bool IsProbabilistic() const { return false; } + bool AllowNonrecoverablePart() const { return false; } + bool RecoverablePartFirst() const { return false; } + + ed25519_MessageAccumulator* NewVerificationAccumulator() const { + return new ed25519_MessageAccumulator; + } + + void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const { + CRYPTOPP_ASSERT(signature != NULLPTR); + CRYPTOPP_ASSERT(signatureLength == SIGNATURE_LENGTH); + ed25519_MessageAccumulator& accum = static_cast(messageAccumulator); + if (signature && signatureLength) + std::memcpy(accum.signature(), signature, STDMIN((size_t)SIGNATURE_LENGTH, signatureLength)); + } + + bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; + + /// \brief Check whether input signature is a valid signature for input message + /// \param stream an std::istream derived class + /// \param signature a pointer to the signature over the message + /// \param signatureLen the size of the signature + /// \return true if the signature is valid, false otherwise + /// \details VerifyStream() handles large streams. The Stream functions were added to + /// ed25519 for signing and verifying files that are too large for a memory allocation. + /// The functions are not present in other library signers and verifiers. + /// \since Crypto++ 8.1 + bool VerifyStream(std::istream& stream, const byte *signature, size_t signatureLen) const; + + DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const { + CRYPTOPP_UNUSED(recoveredMessage); CRYPTOPP_UNUSED(messageAccumulator); + throw NotImplemented("ed25519Verifier: this object does not support recoverable messages"); + } + +protected: + ed25519PublicKey m_key; +}; + +/// \brief Ed25519 signature scheme +/// \sa Ed25519 on the Crypto++ wiki. +/// \since Crypto++ 8.0 +struct ed25519 +{ + /// \brief ed25519 Signer + typedef ed25519Signer Signer; + /// \brief ed25519 Verifier + typedef ed25519Verifier Verifier; +}; + +NAMESPACE_END // CryptoPP + +#endif // CRYPTOPP_XED25519_H diff --git a/third_party/cryptoppwin/include/cryptopp/xtr.h b/third_party/cryptoppwin/include/cryptopp/xtr.h new file mode 100644 index 00000000..3d1c3382 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/xtr.h @@ -0,0 +1,219 @@ +#ifndef CRYPTOPP_XTR_H +#define CRYPTOPP_XTR_H + +/// \file xtr.h +/// \brief The XTR public key system +/// \details The XTR public key system by Arjen K. Lenstra and Eric R. Verheul + +#include "cryptlib.h" +#include "modarith.h" +#include "integer.h" +#include "algebra.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief an element of GF(p^2) +class GFP2Element +{ +public: + GFP2Element() {} + GFP2Element(const Integer &c1, const Integer &c2) : c1(c1), c2(c2) {} + GFP2Element(const byte *encodedElement, unsigned int size) + : c1(encodedElement, size/2), c2(encodedElement+size/2, size/2) {} + + void Encode(byte *encodedElement, unsigned int size) + { + c1.Encode(encodedElement, size/2); + c2.Encode(encodedElement+size/2, size/2); + } + + bool operator==(const GFP2Element &rhs) const {return c1 == rhs.c1 && c2 == rhs.c2;} + bool operator!=(const GFP2Element &rhs) const {return !operator==(rhs);} + + void swap(GFP2Element &a) + { + c1.swap(a.c1); + c2.swap(a.c2); + } + + static const GFP2Element & Zero(); + + Integer c1, c2; +}; + +/// \brief GF(p^2), optimal normal basis +template +class GFP2_ONB : public AbstractRing +{ +public: + typedef F BaseField; + + GFP2_ONB(const Integer &p) : modp(p) + { + if (p%3 != 2) + throw InvalidArgument("GFP2_ONB: modulus must be equivalent to 2 mod 3"); + } + + const Integer& GetModulus() const {return modp.GetModulus();} + + GFP2Element ConvertIn(const Integer &a) const + { + t = modp.Inverse(modp.ConvertIn(a)); + return GFP2Element(t, t); + } + + GFP2Element ConvertIn(const GFP2Element &a) const + {return GFP2Element(modp.ConvertIn(a.c1), modp.ConvertIn(a.c2));} + + GFP2Element ConvertOut(const GFP2Element &a) const + {return GFP2Element(modp.ConvertOut(a.c1), modp.ConvertOut(a.c2));} + + bool Equal(const GFP2Element &a, const GFP2Element &b) const + { + return modp.Equal(a.c1, b.c1) && modp.Equal(a.c2, b.c2); + } + + const Element& Identity() const + { + return GFP2Element::Zero(); + } + + const Element& Add(const Element &a, const Element &b) const + { + result.c1 = modp.Add(a.c1, b.c1); + result.c2 = modp.Add(a.c2, b.c2); + return result; + } + + const Element& Inverse(const Element &a) const + { + result.c1 = modp.Inverse(a.c1); + result.c2 = modp.Inverse(a.c2); + return result; + } + + const Element& Double(const Element &a) const + { + result.c1 = modp.Double(a.c1); + result.c2 = modp.Double(a.c2); + return result; + } + + const Element& Subtract(const Element &a, const Element &b) const + { + result.c1 = modp.Subtract(a.c1, b.c1); + result.c2 = modp.Subtract(a.c2, b.c2); + return result; + } + + Element& Accumulate(Element &a, const Element &b) const + { + modp.Accumulate(a.c1, b.c1); + modp.Accumulate(a.c2, b.c2); + return a; + } + + Element& Reduce(Element &a, const Element &b) const + { + modp.Reduce(a.c1, b.c1); + modp.Reduce(a.c2, b.c2); + return a; + } + + bool IsUnit(const Element &a) const + { + return a.c1.NotZero() || a.c2.NotZero(); + } + + const Element& MultiplicativeIdentity() const + { + result.c1 = result.c2 = modp.Inverse(modp.MultiplicativeIdentity()); + return result; + } + + const Element& Multiply(const Element &a, const Element &b) const + { + t = modp.Add(a.c1, a.c2); + t = modp.Multiply(t, modp.Add(b.c1, b.c2)); + result.c1 = modp.Multiply(a.c1, b.c1); + result.c2 = modp.Multiply(a.c2, b.c2); + result.c1.swap(result.c2); + modp.Reduce(t, result.c1); + modp.Reduce(t, result.c2); + modp.Reduce(result.c1, t); + modp.Reduce(result.c2, t); + return result; + } + + const Element& MultiplicativeInverse(const Element &a) const + { + return result = Exponentiate(a, modp.GetModulus()-2); + } + + const Element& Square(const Element &a) const + { + const Integer &ac1 = (&a == &result) ? (t = a.c1) : a.c1; + result.c1 = modp.Multiply(modp.Subtract(modp.Subtract(a.c2, a.c1), a.c1), a.c2); + result.c2 = modp.Multiply(modp.Subtract(modp.Subtract(ac1, a.c2), a.c2), ac1); + return result; + } + + Element Exponentiate(const Element &a, const Integer &e) const + { + Integer edivp, emodp; + Integer::Divide(emodp, edivp, e, modp.GetModulus()); + Element b = PthPower(a); + return AbstractRing::CascadeExponentiate(a, emodp, b, edivp); + } + + const Element & PthPower(const Element &a) const + { + result = a; + result.c1.swap(result.c2); + return result; + } + + void RaiseToPthPower(Element &a) const + { + a.c1.swap(a.c2); + } + + // a^2 - 2a^p + const Element & SpecialOperation1(const Element &a) const + { + CRYPTOPP_ASSERT(&a != &result); + result = Square(a); + modp.Reduce(result.c1, a.c2); + modp.Reduce(result.c1, a.c2); + modp.Reduce(result.c2, a.c1); + modp.Reduce(result.c2, a.c1); + return result; + } + + // x * z - y * z^p + const Element & SpecialOperation2(const Element &x, const Element &y, const Element &z) const + { + CRYPTOPP_ASSERT(&x != &result && &y != &result && &z != &result); + t = modp.Add(x.c2, y.c2); + result.c1 = modp.Multiply(z.c1, modp.Subtract(y.c1, t)); + modp.Accumulate(result.c1, modp.Multiply(z.c2, modp.Subtract(t, x.c1))); + t = modp.Add(x.c1, y.c1); + result.c2 = modp.Multiply(z.c2, modp.Subtract(y.c2, t)); + modp.Accumulate(result.c2, modp.Multiply(z.c1, modp.Subtract(t, x.c2))); + return result; + } + +protected: + BaseField modp; + mutable GFP2Element result; + mutable Integer t; +}; + +/// \brief Creates primes p,q and generator g for XTR +void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer &q, GFP2Element &g, unsigned int pbits, unsigned int qbits); + +GFP2Element XTR_Exponentiate(const GFP2Element &b, const Integer &e, const Integer &p); + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/xtrcrypt.h b/third_party/cryptoppwin/include/cryptopp/xtrcrypt.h new file mode 100644 index 00000000..0248788c --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/xtrcrypt.h @@ -0,0 +1,55 @@ +#ifndef CRYPTOPP_XTRCRYPT_H +#define CRYPTOPP_XTRCRYPT_H + +/// \file +/// \brief XTR public key system +/// \sa "The XTR public key system" by Arjen K. Lenstra and Eric R. Verheul + +#include "cryptlib.h" +#include "xtr.h" +#include "integer.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief XTR-DH with key validation +class XTR_DH : public SimpleKeyAgreementDomain, public CryptoParameters +{ + typedef XTR_DH ThisClass; + +public: + XTR_DH(const Integer &p, const Integer &q, const GFP2Element &g); + XTR_DH(RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits); + XTR_DH(BufferedTransformation &domainParams); + + void DEREncode(BufferedTransformation &domainParams) const; + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + CryptoParameters & AccessCryptoParameters() {return *this;} + unsigned int AgreedValueLength() const {return 2*m_p.ByteCount();} + unsigned int PrivateKeyLength() const {return m_q.ByteCount();} + unsigned int PublicKeyLength() const {return 2*m_p.ByteCount();} + + void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const; + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const; + bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const; + + const Integer &GetModulus() const {return m_p;} + const Integer &GetSubgroupOrder() const {return m_q;} + const GFP2Element &GetSubgroupGenerator() const {return m_g;} + + void SetModulus(const Integer &p) {m_p = p;} + void SetSubgroupOrder(const Integer &q) {m_q = q;} + void SetSubgroupGenerator(const GFP2Element &g) {m_g = g;} + +private: + unsigned int ExponentBitLength() const; + + Integer m_p, m_q; + GFP2Element m_g; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/xts.h b/third_party/cryptoppwin/include/cryptopp/xts.h new file mode 100644 index 00000000..6eac379a --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/xts.h @@ -0,0 +1,224 @@ +// xts.h - written and placed in the public domain by Jeffrey Walton + +/// \file xts.h +/// \brief Classes for XTS block cipher mode of operation +/// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST +/// SP-800-38E approves the mode for storage devices citing IEEE 1619-2007. +/// IEEE 1619-2007 provides both a reference implementation and test vectors. +/// The IEEE reference implementation fails to arrive at the expected result +/// for some test vectors. +/// \sa Modes of +/// Operation on the Crypto++ wiki, Evaluation of Some +/// Blockcipher Modes of Operation, Recommendation +/// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on +/// Storage Devices, IEEE P1619-2007 +/// and IEEE P1619/XTS, +/// inconsistent reference implementation and test vectors. +/// \since Crypto++ 8.3 + +#ifndef CRYPTOPP_XTS_MODE_H +#define CRYPTOPP_XTS_MODE_H + +#include "cryptlib.h" +#include "secblock.h" +#include "modes.h" +#include "misc.h" + +/// \brief Enable XTS for wide block ciphers +/// \details XTS is only defined for AES. The library can support wide +/// block ciphers like Kaylna and Threefish since we know the polynomials. +/// To enable wide block ciphers define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS +/// to non-zero. Note this is a library compile time define. +/// \details There is risk involved with using XTS with wider block ciphers. +/// According to Phillip Rogaway, "The narrow width of the underlying PRP and +/// the poor treatment of fractional final blocks are problems." +/// \sa Evaluation +/// of Some Blockcipher Modes of Operation +/// \since Crypto++ 8.3 +#ifndef CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS +# define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS 0 +#endif // CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief XTS block cipher mode of operation default implementation +/// \since Crypto++ 8.3 +class CRYPTOPP_NO_VTABLE XTS_ModeBase : public BlockOrientedCipherModeBase +{ +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* StaticAlgorithmName() + {return "XTS";} + + virtual ~XTS_ModeBase() {} + + std::string AlgorithmName() const + {return GetBlockCipher().AlgorithmName() + "/XTS";} + std::string AlgorithmProvider() const + {return GetBlockCipher().AlgorithmProvider();} + + size_t MinKeyLength() const + {return GetBlockCipher().MinKeyLength()*2;} + size_t MaxKeyLength() const + {return GetBlockCipher().MaxKeyLength()*2;} + size_t DefaultKeyLength() const + {return GetBlockCipher().DefaultKeyLength()*2;} + size_t GetValidKeyLength(size_t n) const + {return 2*GetBlockCipher().GetValidKeyLength((n+1)/2);} + bool IsValidKeyLength(size_t keylength) const + {return keylength == GetValidKeyLength(keylength);} + + /// \brief Validates the key length + /// \param length the size of the keying material, in bytes + /// \throw InvalidKeyLength if the key length is invalid + void ThrowIfInvalidKeyLength(size_t length); + + /// Provides the block size of the cipher + /// \return the block size of the cipher, in bytes + unsigned int BlockSize() const + {return GetBlockCipher().BlockSize();} + + /// \brief Provides the input block size most efficient for this cipher + /// \return The input block size that is most efficient for the cipher + /// \details The base class implementation returns MandatoryBlockSize(). + /// \note Optimal input length is + /// n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for + /// any n \> 0. + unsigned int GetOptimalBlockSize() const + {return GetBlockCipher().BlockSize()*ParallelBlocks;} + unsigned int MinLastBlockSize() const + {return GetBlockCipher().BlockSize()+1;} + unsigned int OptimalDataAlignment() const + {return GetBlockCipher().OptimalDataAlignment();} + + /// \brief Validates the block size + /// \param length the block size of the cipher, in bytes + /// \throw InvalidArgument if the block size is invalid + /// \details If CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS is 0, + /// then CIPHER must be a 16-byte block cipher. If + /// CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS is non-zero then + /// CIPHER can be 16, 32, 64, or 128-byte block cipher. + void ThrowIfInvalidBlockSize(size_t length); + + void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs); + IV_Requirement IVRequirement() const {return UNIQUE_IV;} + void Resynchronize(const byte *iv, int ivLength=-1); + void ProcessData(byte *outString, const byte *inString, size_t length); + size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); + + /// \brief Resynchronize the cipher + /// \param sector a 64-bit sector number + /// \param order the endian order the word should be written + /// \details The Resynchronize() overload was provided for API + /// compatibility with the IEEE P1619 paper. + void Resynchronize(word64 sector, ByteOrder order=BIG_ENDIAN_ORDER); + +protected: + virtual void ResizeBuffers(); + + inline size_t ProcessLastPlainBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); + inline size_t ProcessLastCipherBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); + + virtual BlockCipher& AccessBlockCipher() = 0; + virtual BlockCipher& AccessTweakCipher() = 0; + + const BlockCipher& GetBlockCipher() const + {return const_cast(this)->AccessBlockCipher();} + const BlockCipher& GetTweakCipher() const + {return const_cast(this)->AccessTweakCipher();} + + // Buffers are sized based on ParallelBlocks + AlignedSecByteBlock m_xregister; + AlignedSecByteBlock m_xworkspace; + + // Intel lacks the SSE registers to run 8 or 12 parallel blocks. + // Do not change this value after compiling. It has no effect. +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 + enum {ParallelBlocks = 4}; +#else + enum {ParallelBlocks = 12}; +#endif +}; + +/// \brief XTS block cipher mode of operation implementation +/// \tparam CIPHER BlockCipher derived class or type +/// \details XTS_Final() provides access to CIPHER in base class XTS_ModeBase() +/// through an interface. AccessBlockCipher() and AccessTweakCipher() allow +/// the XTS_ModeBase() base class to access the user's block cipher without +/// recompiling the library. +/// \details If CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS is 0, then CIPHER must +/// be a 16-byte block cipher. If CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS is +/// non-zero then CIPHER can be 16, 32, 64, or 128-byte block cipher. +/// There is risk involved with using XTS with wider block ciphers. +/// According to Phillip Rogaway, "The narrow width of the underlying PRP and +/// the poor treatment of fractional final blocks are problems." To enable +/// wide block cipher support define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS to +/// non-zero. +/// \sa Modes of +/// Operation on the Crypto++ wiki, Evaluation of Some +/// Blockcipher Modes of Operation, Recommendation +/// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on +/// Storage Devices, IEEE P1619-2007 +/// and IEEE P1619/XTS, +/// inconsistent reference implementation and test vectors. +/// \since Crypto++ 8.3 +template +class CRYPTOPP_NO_VTABLE XTS_Final : public XTS_ModeBase +{ +protected: + BlockCipher& AccessBlockCipher() + {return *m_cipher;} + BlockCipher& AccessTweakCipher() + {return m_tweaker;} + +protected: + typename CIPHER::Encryption m_tweaker; +}; + +/// \brief XTS block cipher mode of operation +/// \tparam CIPHER BlockCipher derived class or type +/// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST +/// SP-800-38E approves the mode for storage devices citing IEEE 1619-2007. +/// IEEE 1619-2007 provides both a reference implementation and test vectors. +/// The IEEE reference implementation fails to arrive at the expected result +/// for some test vectors. +/// \details XTS is only defined for AES. The library can support wide +/// block ciphers like Kaylna and Threefish since we know the polynomials. +/// There is risk involved with using XTS with wider block ciphers. +/// According to Phillip Rogaway, "The narrow width of the underlying PRP and +/// the poor treatment of fractional final blocks are problems." To enable +/// wide block cipher support define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS to +/// non-zero. +/// \sa Modes of +/// Operation on the Crypto++ wiki, Evaluation of Some +/// Blockcipher Modes of Operation, Recommendation +/// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on +/// Storage Devices, IEEE P1619-2007 +/// and IEEE P1619/XTS, +/// inconsistent reference implementation and test vectors. +/// \since Crypto++ 8.3 +template +struct XTS : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > Decryption; +}; + +// C++03 lacks the mechanics to typedef a template +#define XTS_Mode XTS + +NAMESPACE_END + +#endif // CRYPTOPP_XTS_MODE_H diff --git a/third_party/cryptoppwin/include/cryptopp/zdeflate.h b/third_party/cryptoppwin/include/cryptopp/zdeflate.h new file mode 100644 index 00000000..36ae33c6 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/zdeflate.h @@ -0,0 +1,174 @@ +// zdeflate.h - originally written and placed in the public domain by Wei Dai + +/// \file zdeflate.h +/// \brief DEFLATE compression and decompression (RFC 1951) + +#ifndef CRYPTOPP_ZDEFLATE_H +#define CRYPTOPP_ZDEFLATE_H + +#include "cryptlib.h" +#include "filters.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief Encoding table writer +/// \since Crypto++ 1.0 +class LowFirstBitWriter : public Filter +{ +public: + /// \brief Construct a LowFirstBitWriter + /// \param attachment an attached transformation + LowFirstBitWriter(BufferedTransformation *attachment); + + void PutBits(unsigned long value, unsigned int length); + void FlushBitBuffer(); + void ClearBitBuffer(); + + void StartCounting(); + unsigned long FinishCounting(); + +protected: + bool m_counting; + unsigned long m_bitCount; + unsigned long m_buffer; + unsigned int m_bitsBuffered, m_bytesBuffered; + FixedSizeSecBlock m_outputBuffer; +}; + +/// \brief Huffman Encoder +/// \since Crypto++ 1.0 +class HuffmanEncoder +{ +public: + typedef unsigned int code_t; + typedef unsigned int value_t; + + /// \brief Construct a HuffmanEncoder + HuffmanEncoder() {} + + /// \brief Construct a HuffmanEncoder + /// \param codeBits a table of code bits + /// \param nCodes the number of codes in the table + HuffmanEncoder(const unsigned int *codeBits, unsigned int nCodes); + + /// \brief Initialize or reinitialize this object + /// \param codeBits a table of code bits + /// \param nCodes the number of codes in the table + void Initialize(const unsigned int *codeBits, unsigned int nCodes); + + static void GenerateCodeLengths(unsigned int *codeBits, unsigned int maxCodeBits, const unsigned int *codeCounts, size_t nCodes); + + void Encode(LowFirstBitWriter &writer, value_t value) const; + + struct Code + { + unsigned int code; + unsigned int len; + }; + + SecBlock m_valueToCode; +}; + +/// \brief DEFLATE compressor (RFC 1951) +/// \since Crypto++ 1.0 +class Deflator : public LowFirstBitWriter +{ +public: + /// \brief Deflate level as enumerated values. + enum { + /// \brief Minimum deflation level, fastest speed (0) + MIN_DEFLATE_LEVEL = 0, + /// \brief Default deflation level, compromise between speed (6) + DEFAULT_DEFLATE_LEVEL = 6, + /// \brief Minimum deflation level, slowest speed (9) + MAX_DEFLATE_LEVEL = 9}; + + /// \brief Windows size as enumerated values. + enum { + /// \brief Minimum window size, smallest table (9) + MIN_LOG2_WINDOW_SIZE = 9, + /// \brief Default window size (15) + DEFAULT_LOG2_WINDOW_SIZE = 15, + /// \brief Maximum window size, largest table (15) + MAX_LOG2_WINDOW_SIZE = 15}; + + /// \brief Construct a Deflator compressor + /// \param attachment an attached transformation + /// \param deflateLevel the deflate level + /// \param log2WindowSize the window size + /// \param detectUncompressible flag to detect if data is compressible + /// \details detectUncompressible makes it faster to process uncompressible files, but + /// if a file has both compressible and uncompressible parts, it may fail to compress + /// some of the compressible parts. + Deflator(BufferedTransformation *attachment=NULLPTR, int deflateLevel=DEFAULT_DEFLATE_LEVEL, int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true); + /// \brief Construct a Deflator compressor + /// \param parameters a set of NameValuePairs to initialize this object + /// \param attachment an attached transformation + /// \details Possible parameter names: Log2WindowSize, DeflateLevel, DetectUncompressible + Deflator(const NameValuePairs ¶meters, BufferedTransformation *attachment=NULLPTR); + + /// \brief Sets the deflation level + /// \param deflateLevel the level of deflation + /// \details SetDeflateLevel can be used to set the deflate level in the middle of compression + void SetDeflateLevel(int deflateLevel); + + /// \brief Retrieves the deflation level + /// \return the level of deflation + int GetDeflateLevel() const {return m_deflateLevel;} + + /// \brief Retrieves the window size + /// \return the windows size + int GetLog2WindowSize() const {return m_log2WindowSize;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedFlush(bool hardFlush, bool blocking); + +protected: + virtual void WritePrestreamHeader() {} + virtual void ProcessUncompressedData(const byte *string, size_t length) + {CRYPTOPP_UNUSED(string), CRYPTOPP_UNUSED(length);} + virtual void WritePoststreamTail() {} + + enum {STORED = 0, STATIC = 1, DYNAMIC = 2}; + enum {MIN_MATCH = 3, MAX_MATCH = 258}; + + void InitializeStaticEncoders(); + void Reset(bool forceReset = false); + unsigned int FillWindow(const byte *str, size_t length); + unsigned int ComputeHash(const byte *str) const; + unsigned int LongestMatch(unsigned int &bestMatch) const; + void InsertString(unsigned int start); + void ProcessBuffer(); + + void LiteralByte(byte b); + void MatchFound(unsigned int distance, unsigned int length); + void EncodeBlock(bool eof, unsigned int blockType); + void EndBlock(bool eof); + + struct EncodedMatch + { + unsigned literalCode : 9; + unsigned literalExtra : 5; + unsigned distanceCode : 5; + unsigned distanceExtra : 13; + }; + + int m_deflateLevel, m_log2WindowSize, m_compressibleDeflateLevel; + unsigned int m_detectSkip, m_detectCount; + unsigned int DSIZE, DMASK, HSIZE, HMASK, GOOD_MATCH, MAX_LAZYLENGTH, MAX_CHAIN_LENGTH; + bool m_headerWritten, m_matchAvailable; + unsigned int m_dictionaryEnd, m_stringStart, m_lookahead, m_minLookahead, m_previousMatch, m_previousLength; + HuffmanEncoder m_staticLiteralEncoder, m_staticDistanceEncoder, m_dynamicLiteralEncoder, m_dynamicDistanceEncoder; + SecByteBlock m_byteBuffer; + SecBlock m_head, m_prev; + FixedSizeSecBlock m_literalCounts; + FixedSizeSecBlock m_distanceCounts; + SecBlock m_matchBuffer; + unsigned int m_matchBufferEnd, m_blockStart, m_blockLength; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/zinflate.h b/third_party/cryptoppwin/include/cryptopp/zinflate.h new file mode 100644 index 00000000..db9b9425 --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/zinflate.h @@ -0,0 +1,164 @@ +// zinflate.h - originally written and placed in the public domain by Wei Dai + +/// \file zinflate.h +/// \brief DEFLATE compression and decompression (RFC 1951) + +#ifndef CRYPTOPP_ZINFLATE_H +#define CRYPTOPP_ZINFLATE_H + +#include "cryptlib.h" +#include "secblock.h" +#include "filters.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \since Crypto++ 1.0 +class LowFirstBitReader +{ +public: + LowFirstBitReader(BufferedTransformation &store) + : m_store(store), m_buffer(0), m_bitsBuffered(0) {} + unsigned int BitsBuffered() const {return m_bitsBuffered;} + unsigned long PeekBuffer() const {return m_buffer;} + bool FillBuffer(unsigned int length); + unsigned long PeekBits(unsigned int length); + void SkipBits(unsigned int length); + unsigned long GetBits(unsigned int length); + +private: + BufferedTransformation &m_store; + unsigned long m_buffer; + unsigned int m_bitsBuffered; +}; + +struct CodeLessThan; + +/// \brief Huffman Decoder +/// \since Crypto++ 1.0 +class HuffmanDecoder +{ +public: + typedef unsigned int code_t; + typedef unsigned int value_t; + enum {MAX_CODE_BITS = sizeof(code_t)*8}; + + class Err : public Exception {public: Err(const std::string &what) : Exception(INVALID_DATA_FORMAT, "HuffmanDecoder: " + what) {}}; + + HuffmanDecoder() : m_maxCodeBits(0), m_cacheBits(0), m_cacheMask(0), m_normalizedCacheMask(0) {} + HuffmanDecoder(const unsigned int *codeBitLengths, unsigned int nCodes) + : m_maxCodeBits(0), m_cacheBits(0), m_cacheMask(0), m_normalizedCacheMask(0) + {Initialize(codeBitLengths, nCodes);} + + void Initialize(const unsigned int *codeBitLengths, unsigned int nCodes); + unsigned int Decode(code_t code, /* out */ value_t &value) const; + bool Decode(LowFirstBitReader &reader, value_t &value) const; + +private: + friend struct CodeLessThan; + + struct CodeInfo + { + CodeInfo(code_t code=0, unsigned int len=0, value_t value=0) : code(code), len(len), value(value) {} + inline bool operator<(const CodeInfo &rhs) const {return code < rhs.code;} + code_t code; + unsigned int len; + value_t value; + }; + + struct LookupEntry + { + unsigned int type; + union + { + value_t value; + const CodeInfo *begin; + }; + union + { + unsigned int len; + const CodeInfo *end; + }; + }; + + static code_t NormalizeCode(code_t code, unsigned int codeBits); + void FillCacheEntry(LookupEntry &entry, code_t normalizedCode) const; + + unsigned int m_maxCodeBits, m_cacheBits, m_cacheMask, m_normalizedCacheMask; + std::vector > m_codeToValue; + mutable std::vector > m_cache; +}; + +/// \brief DEFLATE decompressor (RFC 1951) +/// \since Crypto++ 1.0 +class Inflator : public AutoSignaling +{ +public: + class Err : public Exception + { + public: + Err(ErrorType e, const std::string &s) + : Exception(e, s) {} + }; + /// \brief Exception thrown when a truncated stream is encountered + class UnexpectedEndErr : public Err {public: UnexpectedEndErr() : Err(INVALID_DATA_FORMAT, "Inflator: unexpected end of compressed block") {}}; + /// \brief Exception thrown when a bad block is encountered + class BadBlockErr : public Err {public: BadBlockErr() : Err(INVALID_DATA_FORMAT, "Inflator: error in compressed block") {}}; + /// \brief Exception thrown when an invalid distance is encountered + class BadDistanceErr : public Err {public: BadDistanceErr() : Err(INVALID_DATA_FORMAT, "Inflator: error in bit distance") {}}; + + /// \brief RFC 1951 Decompressor + /// \param attachment the filter's attached transformation + /// \param repeat decompress multiple compressed streams in series + /// \param autoSignalPropagation 0 to turn off MessageEnd signal + Inflator(BufferedTransformation *attachment = NULLPTR, bool repeat = false, int autoSignalPropagation = -1); + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedFlush(bool hardFlush, bool blocking); + + virtual unsigned int GetLog2WindowSize() const {return 15;} + +protected: + ByteQueue m_inQueue; + +private: + virtual unsigned int MaxPrestreamHeaderSize() const {return 0;} + virtual void ProcessPrestreamHeader() {} + virtual void ProcessDecompressedData(const byte *string, size_t length) + {AttachedTransformation()->Put(string, length);} + virtual unsigned int MaxPoststreamTailSize() const {return 0;} + virtual void ProcessPoststreamTail() {} + + void ProcessInput(bool flush); + void DecodeHeader(); + bool DecodeBody(); + void FlushOutput(); + void OutputByte(byte b); + void OutputString(const byte *string, size_t length); + void OutputPast(unsigned int length, unsigned int distance); + + void CreateFixedDistanceDecoder(); + void CreateFixedLiteralDecoder(); + + const HuffmanDecoder& GetLiteralDecoder(); + const HuffmanDecoder& GetDistanceDecoder(); + + enum State {PRE_STREAM, WAIT_HEADER, DECODING_BODY, POST_STREAM, AFTER_END}; + State m_state; + bool m_repeat, m_eof, m_wrappedAround; + byte m_blockType; + word16 m_storedLen; + enum NextDecode {LITERAL, LENGTH_BITS, DISTANCE, DISTANCE_BITS}; + NextDecode m_nextDecode; + unsigned int m_literal, m_distance; // for LENGTH_BITS or DISTANCE_BITS + HuffmanDecoder m_dynamicLiteralDecoder, m_dynamicDistanceDecoder; + member_ptr m_fixedLiteralDecoder, m_fixedDistanceDecoder; + LowFirstBitReader m_reader; + SecByteBlock m_window; + size_t m_current, m_lastFlush; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/include/cryptopp/zlib.h b/third_party/cryptoppwin/include/cryptopp/zlib.h new file mode 100644 index 00000000..b5fca51c --- /dev/null +++ b/third_party/cryptoppwin/include/cryptopp/zlib.h @@ -0,0 +1,65 @@ +// zlib.h - originally written and placed in the public domain by Wei Dai + +/// \file zlib.h +/// \brief ZLIB compression and decompression (RFC 1950) + +#ifndef CRYPTOPP_ZLIB_H +#define CRYPTOPP_ZLIB_H + +#include "cryptlib.h" +#include "adler32.h" +#include "zdeflate.h" +#include "zinflate.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// ZLIB Compressor (RFC 1950) +class ZlibCompressor : public Deflator +{ +public: + ZlibCompressor(BufferedTransformation *attachment=NULLPTR, unsigned int deflateLevel=DEFAULT_DEFLATE_LEVEL, unsigned int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true) + : Deflator(attachment, deflateLevel, log2WindowSize, detectUncompressible) {} + ZlibCompressor(const NameValuePairs ¶meters, BufferedTransformation *attachment=NULLPTR) + : Deflator(parameters, attachment) {} + + unsigned int GetCompressionLevel() const; + +protected: + void WritePrestreamHeader(); + void ProcessUncompressedData(const byte *string, size_t length); + void WritePoststreamTail(); + + Adler32 m_adler32; +}; + +/// ZLIB Decompressor (RFC 1950) +class ZlibDecompressor : public Inflator +{ +public: + typedef Inflator::Err Err; + class HeaderErr : public Err {public: HeaderErr() : Err(INVALID_DATA_FORMAT, "ZlibDecompressor: header decoding error") {}}; + class Adler32Err : public Err {public: Adler32Err() : Err(DATA_INTEGRITY_CHECK_FAILED, "ZlibDecompressor: ADLER32 check error") {}}; + class UnsupportedAlgorithm : public Err {public: UnsupportedAlgorithm() : Err(INVALID_DATA_FORMAT, "ZlibDecompressor: unsupported algorithm") {}}; + class UnsupportedPresetDictionary : public Err {public: UnsupportedPresetDictionary() : Err(INVALID_DATA_FORMAT, "ZlibDecompressor: unsupported preset dictionary") {}}; + + /// \brief Construct a ZlibDecompressor + /// \param attachment a \ BufferedTransformation to attach to this object + /// \param repeat decompress multiple compressed streams in series + /// \param autoSignalPropagation 0 to turn off MessageEnd signal + ZlibDecompressor(BufferedTransformation *attachment = NULLPTR, bool repeat = false, int autoSignalPropagation = -1); + unsigned int GetLog2WindowSize() const {return m_log2WindowSize;} + +private: + unsigned int MaxPrestreamHeaderSize() const {return 2;} + void ProcessPrestreamHeader(); + void ProcessDecompressedData(const byte *string, size_t length); + unsigned int MaxPoststreamTailSize() const {return 4;} + void ProcessPoststreamTail(); + + unsigned int m_log2WindowSize; + Adler32 m_adler32; +}; + +NAMESPACE_END + +#endif diff --git a/third_party/cryptoppwin/lib/cryptlib.lib b/third_party/cryptoppwin/lib/cryptlib.lib new file mode 100644 index 00000000..446c5e20 Binary files /dev/null and b/third_party/cryptoppwin/lib/cryptlib.lib differ diff --git a/third_party/cryptoppwin/lib/cryptlibd.lib b/third_party/cryptoppwin/lib/cryptlibd.lib new file mode 100644 index 00000000..e6173dc0 Binary files /dev/null and b/third_party/cryptoppwin/lib/cryptlibd.lib differ